From 2b0a6b995a3eaf3b54e480b8b7bcbe43fd20b5d9 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 26 Dec 2020 16:17:01 +0100 Subject: [PATCH 1/7] display: Add a way to query system DPI scaling See #426 --- doc/ReleaseNotes | 1 + panda/src/display/config_display.cxx | 8 ++++++ panda/src/display/config_display.h | 1 + panda/src/display/graphicsPipe.cxx | 32 ++++++++++++++++++++++++ panda/src/display/graphicsPipe.h | 4 +++ panda/src/windisplay/winGraphicsPipe.cxx | 16 ++++++++++++ panda/src/x11display/x11GraphicsPipe.cxx | 24 ++++++++++++++++++ 7 files changed, 86 insertions(+) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 83fe5b1bd5..392589b07c 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -10,6 +10,7 @@ Recommended maintenance release. * Fix sounds resuming on reactivation if stop() was called while inactive (#559) * Collision traverser now releases GIL during traversal (#1033) * Fix crash caused by some gamepad drivers on Linux (#1066) +* Add GraphicsPipe::get_display_zoom() for querying system DPI scaling * Skinning-enabled shaders can now properly render unskinned models as well * BitMask, SparseArray, BitArray types can now be pickled (#886) * VFSImporter now properly detects source file encodings in Python 3 diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index 965d68f4e3..2cb2f40c27 100644 --- a/panda/src/display/config_display.cxx +++ b/panda/src/display/config_display.cxx @@ -478,6 +478,14 @@ ConfigVariableBool sync_video "cheesy estimate of scene complexity. Some drivers may ignore " "this request.")); +ConfigVariableDouble display_zoom +("display-zoom", 0.0, + PRC_DESC("If this is set to a value other than 0.0, it overrides the detected " + "system DPI scaling. GraphicsPipe::get_display_zoom() will instead " + "return whatever was passed in here. You should generally only " + "change this based on a user preference change or to test how the UI " + "will look on monitors with different pixel densities.")); + /** * Initializes the library. This must be called at least once before any of * the functions or classes in this library can be used. Normally it will be diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index 21f1acb510..fb4da08b8d 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -108,6 +108,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableDouble pixel_zoom; extern EXPCL_PANDA_DISPLAY ConfigVariableColor background_color; extern EXPCL_PANDA_DISPLAY ConfigVariableBool sync_video; +extern EXPCL_PANDA_DISPLAY ConfigVariableDouble display_zoom; extern EXPCL_PANDA_DISPLAY void init_libdisplay(); diff --git a/panda/src/display/graphicsPipe.cxx b/panda/src/display/graphicsPipe.cxx index 52ccfa426d..e2e55b5db0 100644 --- a/panda/src/display/graphicsPipe.cxx +++ b/panda/src/display/graphicsPipe.cxx @@ -99,6 +99,9 @@ static void update_memory_info(DisplayInformation *info) { } #endif +// Temporarily declared as global float. +static PN_stdfloat detected_display_zoom = 1.0; + TypeHandle GraphicsPipe::_type_handle; /** @@ -268,6 +271,35 @@ make_output(const std::string &name, return nullptr; } +/** + * Returns the display zoom factor configured in the operating system. If the + * operating system automatically scales windows to match the DPI (such as when + * dpi-aware is set to false), this will be 1.0. Otherwise, this will be set to + * a value approximating the density of the monitor divided by the standard + * density of the operating system (usually 96), yielding a value like 1.5 or + * 2.0. + * + * @since 1.10.8 + */ +PN_stdfloat GraphicsPipe:: +get_display_zoom() const { + if (display_zoom.get_num_words() > 0) { + double override = display_zoom.get_value(); + if (override != 0.0) { + return override; + } + } + return detected_display_zoom; +} + +/** + * Called by derived class to set the display zoom factor. + */ +void GraphicsPipe:: +set_detected_display_zoom(PN_stdfloat zoom) { + detected_display_zoom = zoom; +} + /** * Gets the pipe's DisplayInformation. */ diff --git a/panda/src/display/graphicsPipe.h b/panda/src/display/graphicsPipe.h index ef3a3b8496..156467f66a 100644 --- a/panda/src/display/graphicsPipe.h +++ b/panda/src/display/graphicsPipe.h @@ -91,8 +91,10 @@ PUBLISHED: INLINE int get_display_width() const; INLINE int get_display_height() const; + PN_stdfloat get_display_zoom() const; MAKE_PROPERTY(display_width, get_display_width); MAKE_PROPERTY(display_height, get_display_height); + MAKE_PROPERTY(display_zoom, get_display_zoom); DisplayInformation *get_display_information(); MAKE_PROPERTY(display_information, get_display_information); @@ -115,6 +117,8 @@ public: virtual PT(GraphicsStateGuardian) make_callback_gsg(GraphicsEngine *engine); protected: + void set_detected_display_zoom(PN_stdfloat zoom); + virtual void close_gsg(GraphicsStateGuardian *gsg); virtual PT(GraphicsOutput) make_output(const std::string &name, diff --git a/panda/src/windisplay/winGraphicsPipe.cxx b/panda/src/windisplay/winGraphicsPipe.cxx index 7da40c64f1..b89d022ca8 100644 --- a/panda/src/windisplay/winGraphicsPipe.cxx +++ b/panda/src/windisplay/winGraphicsPipe.cxx @@ -239,6 +239,22 @@ WinGraphicsPipe() { windisplay_cat.debug() << "Calling SetProcessDpiAwareness().\n"; } pfnSetProcessDpiAwareness(Process_Per_Monitor_DPI_Aware); + + HDC dc = GetDC(nullptr); + if (dc) { + int dpi = GetDeviceCaps(dc, LOGPIXELSX); + if (dpi > 0) { + PN_stdfloat zoom = (double)dpi / 96.0; + set_detected_display_zoom(zoom); + + if (windisplay_cat.is_debug()) { + windisplay_cat.debug() + << "Determined display zoom to be " << zoom + << " based on LOGPIXELSX " << dpi << "\n"; + } + } + ReleaseDC(nullptr, dc); + } } } } diff --git a/panda/src/x11display/x11GraphicsPipe.cxx b/panda/src/x11display/x11GraphicsPipe.cxx index 64393a1541..e871cb20a7 100644 --- a/panda/src/x11display/x11GraphicsPipe.cxx +++ b/panda/src/x11display/x11GraphicsPipe.cxx @@ -16,6 +16,7 @@ #include "config_x11display.h" #include "frameBufferProperties.h" #include "displayInformation.h" +#include "pstrtod.h" #include @@ -300,6 +301,29 @@ x11GraphicsPipe(const std::string &display) : XFree(im_supported_styles); */ + const char *dpi = XGetDefault(_display, "Xft", "dpi"); + if (dpi != nullptr) { + char *endptr = nullptr; + double result = pstrtod(dpi, &endptr); + if (result != 0 && !cnan(result) && endptr[0] == '\0') { + result /= 96; + set_detected_display_zoom(result); + + if (x11display_cat.is_debug()) { + x11display_cat.debug() + << "Determined display zoom to be " << result + << " based on specified Xft.dpi " << dpi << "\n"; + } + } else { + x11display_cat.warning() + << "Unable to determine display zoom because Xft.dpi is invalid: " + << dpi << "\n"; + } + } else if (x11display_cat.is_debug()) { + x11display_cat.debug() + << "Unable to determine display zoom because Xft.dpi was not set.\n"; + } + // Get some X atom numbers. _wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false); _net_wm_pid = XInternAtom(_display, "_NET_WM_PID", false); From e7a6d735e3fe9464ab2081cb89c1a8d2b059ce71 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 27 Dec 2020 10:48:12 +0100 Subject: [PATCH 2/7] dgui: Add "versionadded" to docstrings of newly added methods --- direct/src/gui/OnscreenText.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/direct/src/gui/OnscreenText.py b/direct/src/gui/OnscreenText.py index 13a284622f..b6d3932943 100644 --- a/direct/src/gui/OnscreenText.py +++ b/direct/src/gui/OnscreenText.py @@ -314,6 +314,9 @@ class OnscreenText(NodePath): text = property(getText, setText) def setTextX(self, x): + """ + .. versionadded:: 1.10.8 + """ self.setTextPos(x, self.__pos[1]) def setX(self, x): @@ -324,6 +327,9 @@ class OnscreenText(NodePath): self.setTextPos(x, self.__pos[1]) def setTextY(self, y): + """ + .. versionadded:: 1.10.8 + """ self.setTextPos(self.__pos[0], y) def setY(self, y): @@ -336,6 +342,8 @@ class OnscreenText(NodePath): def setTextPos(self, x, y=None): """ Position the onscreen text in 2d screen space + + .. versionadded:: 1.10.8 """ if y is None: self.__pos = tuple(x) @@ -344,6 +352,9 @@ class OnscreenText(NodePath): self.updateTransformMat() def getTextPos(self): + """ + .. versionadded:: 1.10.8 + """ return self.__pos text_pos = property(getTextPos, setTextPos) @@ -370,6 +381,8 @@ class OnscreenText(NodePath): def setTextR(self, r): """setTextR(self, float) Rotates the text around the screen's normal. + + .. versionadded:: 1.10.8 """ self.__roll = -r self.updateTransformMat() @@ -402,6 +415,8 @@ class OnscreenText(NodePath): """setTextScale(self, float, float) Scale the text in 2d space. You may specify either a single uniform scale, or two scales, or a tuple of two scales. + + .. versionadded:: 1.10.8 """ if sy is None: @@ -414,6 +429,9 @@ class OnscreenText(NodePath): self.updateTransformMat() def getTextScale(self): + """ + .. versionadded:: 1.10.8 + """ return self.__scale text_scale = property(getTextScale, setTextScale) From d39d40b1fc4dee02ad913e033790a5a6a591c659 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 27 Dec 2020 11:06:21 +0100 Subject: [PATCH 3/7] readme: Update version number in download link to 1.10.8 [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 508d8eb78b..eef12fb903 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Installing Panda3D ================== The latest Panda3D SDK can be downloaded from -[this page](https://www.panda3d.org/download/sdk-1-10-7/). +[this page](https://www.panda3d.org/download/sdk-1-10-8/). If you are familiar with installing Python packages, you can use the following command: From 21aa31f8c0d14a1a089f381f7805d1eb46ffef36 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 28 Dec 2020 12:07:17 +0100 Subject: [PATCH 4/7] gobj: Fix build error on Windows --- panda/src/gobj/vertexDataSaveFile.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/gobj/vertexDataSaveFile.cxx b/panda/src/gobj/vertexDataSaveFile.cxx index 37839099dc..1cc96719c7 100644 --- a/panda/src/gobj/vertexDataSaveFile.cxx +++ b/panda/src/gobj/vertexDataSaveFile.cxx @@ -313,7 +313,7 @@ read_data(unsigned char *data, size_t size, VertexDataSaveBlock *block) { } success = GetOverlappedResult(_handle, &overlapped, &bytes_read, false); } - nassertr(bytes_read == size, nullptr); + nassertr(bytes_read == size, false); double finish_time = ClockObject::get_global_clock()->get_real_time(); if (gobj_cat.is_debug()) { gobj_cat.debug() From f2e66a280ccdd18a3f1984ddde3e4dde8ec0d252 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 28 Dec 2020 15:27:56 +0100 Subject: [PATCH 5/7] deploy-stub: Fix immediate exit on Windows if no log_filename is set --- pandatool/src/deploy-stub/deploy-stub.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pandatool/src/deploy-stub/deploy-stub.c b/pandatool/src/deploy-stub/deploy-stub.c index 1668b63c0d..21b99b2fb0 100644 --- a/pandatool/src/deploy-stub/deploy-stub.c +++ b/pandatool/src/deploy-stub/deploy-stub.c @@ -360,15 +360,20 @@ static int enable_line_buffering(PyObject *file) { if (method != NULL) { PyObject *result = PyObject_Call(method, args, kwargs); Py_DECREF(method); + Py_DECREF(kwargs); + Py_DECREF(args); if (result != NULL) { Py_DECREF(result); } else { PyErr_Clear(); return 0; } + } else { + Py_DECREF(kwargs); + Py_DECREF(args); + PyErr_Clear(); + return 0; } - Py_DECREF(kwargs); - Py_DECREF(args); #else /* Older versions just don't expose a way to reconfigure(), but it's still safe to override the property; we just have to use a hack to do it, From 5dc5d009c1f20333bdc8e08d4cf146789f21c5ee Mon Sep 17 00:00:00 2001 From: janEntikan Date: Sun, 27 Dec 2020 16:26:46 +0100 Subject: [PATCH 6/7] extensions_native: fix missing include for subdivideCollision() Closes #1084 --- direct/src/extensions_native/NodePath_extensions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/direct/src/extensions_native/NodePath_extensions.py b/direct/src/extensions_native/NodePath_extensions.py index 6756819f47..ffb55daceb 100644 --- a/direct/src/extensions_native/NodePath_extensions.py +++ b/direct/src/extensions_native/NodePath_extensions.py @@ -789,6 +789,7 @@ def r_subdivideCollisions(self, solids, numSolidsInLeaves): return newSolids def r_constructCollisionTree(self, solidTree, parentNode, colName): + from panda3d.core import CollisionNode for item in solidTree: if type(item[0]) == type([]): newNode = parentNode.attachNewNode('%s-branch' % colName) From 90fb31ac219f7fb5e314686fed03cb069ef81554 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 28 Dec 2020 16:23:04 +0100 Subject: [PATCH 7/7] ffmpeg: Fix crash cleaning up audio/video context --- panda/src/ffmpeg/ffmpegAudioCursor.cxx | 2 +- panda/src/ffmpeg/ffmpegVideoCursor.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.cxx b/panda/src/ffmpeg/ffmpegAudioCursor.cxx index c7ee596220..62a20b12ed 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.cxx +++ b/panda/src/ffmpeg/ffmpegAudioCursor.cxx @@ -224,7 +224,7 @@ cleanup() { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) avcodec_free_context(&_audio_ctx); #else - delete _audio_ctx; + av_free(_audio_ctx); #endif } _audio_ctx = nullptr; diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index 23314561e9..b6bf441857 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -607,7 +607,7 @@ close_stream() { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 52, 0) avcodec_free_context(&_video_ctx); #else - delete _video_ctx; + av_free(_video_ctx); #endif } _video_ctx = nullptr;