From 32f905406790d261241bf30aec6b8e193b96efd3 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 12:52:44 +0100 Subject: [PATCH 01/15] prc: Add `ConfigVariableFilename.__fspath__()` Fixes #1406 --- dtool/src/prc/configVariableFilename.I | 11 +++++++++++ dtool/src/prc/configVariableFilename.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/dtool/src/prc/configVariableFilename.I b/dtool/src/prc/configVariableFilename.I index 51013ddfcf..e4bb29faae 100644 --- a/dtool/src/prc/configVariableFilename.I +++ b/dtool/src/prc/configVariableFilename.I @@ -218,6 +218,17 @@ set_word(size_t n, const Filename &value) { set_string_word(n, value); } +/** + * Allows a ConfigVariableFilename object to be passed to any Python function + * that accepts an os.PathLike object. + * + * @since 1.10.13 + */ +INLINE std::wstring ConfigVariableFilename:: +__fspath__() const { + return get_ref_value().to_os_specific_w(); +} + /** * Returns the variable's value, as a reference into the config variable * itself. This is the internal method that implements get_value(), which diff --git a/dtool/src/prc/configVariableFilename.h b/dtool/src/prc/configVariableFilename.h index 7537e22117..762435201f 100644 --- a/dtool/src/prc/configVariableFilename.h +++ b/dtool/src/prc/configVariableFilename.h @@ -60,6 +60,8 @@ PUBLISHED: INLINE Filename get_word(size_t n) const; INLINE void set_word(size_t n, const Filename &value); + INLINE std::wstring __fspath__() const; + private: void reload_cache(); INLINE const Filename &get_ref_value() const; From 02028aa789766ba438c33abe15369fdbf3ed801f Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 12:56:37 +0100 Subject: [PATCH 02/15] Update BACKERS.md [skip ci] --- BACKERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BACKERS.md b/BACKERS.md index fec17f55ef..99b14faf77 100644 --- a/BACKERS.md +++ b/BACKERS.md @@ -26,6 +26,7 @@ This is a list of all the people who are contributing financially to Panda3D. I * Brian Lach * Maxwell Dreytser * SureBet +* Gyedo Jeon ## Backers From 95a77e4f757e11b8dbde501b7ba5fc246426eea2 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 12:57:02 +0100 Subject: [PATCH 03/15] showbase: Add `do_events()` and `process_event()` snake_case aliases --- direct/src/showbase/EventManager.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/direct/src/showbase/EventManager.py b/direct/src/showbase/EventManager.py index 319503b414..290ea457d2 100644 --- a/direct/src/showbase/EventManager.py +++ b/direct/src/showbase/EventManager.py @@ -179,3 +179,6 @@ class EventManager: # since the task removal itself might also fire off an event. if self.eventQueue is not None: self.eventQueue.clear() + + do_events = doEvents + process_event = processEvent From 2c9deaaaf06fba7b4d5f71e9e75cd4919aa5a18e Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 12:57:45 +0100 Subject: [PATCH 04/15] glgsg: Fix 1 texture stage limit when setting `gl-version 3 2` or higher Fixes #1404 --- panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 24bd54134d..3e22c98eb3 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -11623,7 +11623,17 @@ set_state_and_transform(const RenderState *target, if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) || !_state_mask.get_bit(texture_slot)) { PStatGPUTimer timer(this, _draw_set_state_texture_pcollector); - determine_target_texture(); + if (has_fixed_function_pipeline() || + _current_shader == nullptr || + _current_shader == _default_shader) { + determine_target_texture(); + } else { + // If we have a custom shader, don't filter down the list of textures. + _target_texture = (const TextureAttrib *) + _target_rs->get_attrib_def(TextureAttrib::get_class_slot()); + _target_tex_gen = (const TexGenAttrib *) + _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()); + } do_issue_texture(); // Since the TexGen and TexMatrix states depend partly on the particular From 8a46c3dc640bd44819cc7c0344b5ec537cebcf73 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 13:36:14 +0100 Subject: [PATCH 05/15] windisplay: Only release capture when last mouse button is released This fixes issues with lost up events when dragging out of the window with multiple buttons held Fixes #1396 --- panda/src/windisplay/winGraphicsWindow.cxx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 8b70b51938..1ca0425273 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -1671,7 +1671,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (_lost_keypresses) { resend_lost_keypresses(); } - ReleaseCapture(); + if (wparam == 0) { + ReleaseCapture(); + } _input->button_up(MouseButton::button(0), get_message_time()); return 0; @@ -1679,7 +1681,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (_lost_keypresses) { resend_lost_keypresses(); } - ReleaseCapture(); + if (wparam == 0) { + ReleaseCapture(); + } _input->button_up(MouseButton::button(1), get_message_time()); return 0; @@ -1687,7 +1691,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (_lost_keypresses) { resend_lost_keypresses(); } - ReleaseCapture(); + if (wparam == 0) { + ReleaseCapture(); + } _input->button_up(MouseButton::button(2), get_message_time()); return 0; @@ -1696,7 +1702,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (_lost_keypresses) { resend_lost_keypresses(); } - ReleaseCapture(); + if (wparam == 0) { + ReleaseCapture(); + } int whichButton = GET_XBUTTON_WPARAM(wparam); if (whichButton == XBUTTON1) { _input->button_up(MouseButton::button(3), get_message_time()); From ff9ff688be5c017551f412aee00653b5332bddb1 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 13:48:23 +0100 Subject: [PATCH 06/15] tform: Fix "without" event generation when mouse leaves window Fixes #1400 --- panda/src/tform/mouseWatcher.cxx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/panda/src/tform/mouseWatcher.cxx b/panda/src/tform/mouseWatcher.cxx index 54caa1cd88..17b5873d8b 100644 --- a/panda/src/tform/mouseWatcher.cxx +++ b/panda/src/tform/mouseWatcher.cxx @@ -724,19 +724,14 @@ clear_current_regions() { while (old_ri != _current_regions.end()) { // Here's a region we don't have any more. MouseWatcherRegion *old_region = (*old_ri); - old_region->exit_region(param); - throw_event_pattern(_leave_pattern, old_region, ButtonHandle::none()); - if (_preferred_region == old_region) { - _preferred_region = nullptr; - } + without_region(old_region, param); ++old_ri; } _current_regions.clear(); if (_preferred_region != nullptr) { - _preferred_region->exit_region(param); - throw_event_pattern(_leave_pattern, _preferred_region, ButtonHandle::none()); + exit_region(_preferred_region, param); _preferred_region = nullptr; } } From 0a8e4e31f8b3383ee00b4aa27aaea912d3eab371 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 14:42:51 +0100 Subject: [PATCH 07/15] makepanda: Add handling for manylinux_2_28 Note that this version drops 32-bit intel support --- makepanda/makepanda.py | 32 ++++++++++++++++++++------------ makepanda/makewheel.py | 2 ++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index b2adc446e8..23fd57afaa 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -442,8 +442,9 @@ if P3DSUFFIX is None: # Now determine the distutils-style platform tag for the target system. target = GetTarget() +target_arch = GetTargetArch() if target == 'windows': - if GetTargetArch() == 'x64': + if target_arch == 'x64': PLATFORM = 'win-amd64' else: PLATFORM = 'win32' @@ -460,7 +461,7 @@ elif target == 'darwin': arch_tag = None if not OSX_ARCHS: - arch_tag = GetTargetArch() + arch_tag = target_arch elif len(OSX_ARCHS) == 1: arch_tag = OSX_ARCHS[0] elif frozenset(OSX_ARCHS) == frozenset(('i386', 'ppc')): @@ -482,45 +483,53 @@ elif target == 'darwin': elif target == 'linux' and (os.path.isfile("/lib/libc-2.5.so") or os.path.isfile("/lib64/libc-2.5.so")) and os.path.isdir("/opt/python"): # This is manylinux1. A bit of a sloppy check, though. - if GetTargetArch() in ('x86_64', 'amd64'): + if target_arch in ('x86_64', 'amd64'): PLATFORM = 'manylinux1-x86_64' - elif GetTargetArch() in ('arm64', 'aarch64'): + elif target_arch in ('arm64', 'aarch64'): PLATFORM = 'manylinux1-aarch64' else: PLATFORM = 'manylinux1-i686' elif target == 'linux' and (os.path.isfile("/lib/libc-2.12.so") or os.path.isfile("/lib64/libc-2.12.so")) and os.path.isdir("/opt/python"): # Same sloppy check for manylinux2010. - if GetTargetArch() in ('x86_64', 'amd64'): + if target_arch in ('x86_64', 'amd64'): PLATFORM = 'manylinux2010-x86_64' - elif GetTargetArch() in ('arm64', 'aarch64'): + elif target_arch in ('arm64', 'aarch64'): PLATFORM = 'manylinux2010-aarch64' else: PLATFORM = 'manylinux2010-i686' elif target == 'linux' and (os.path.isfile("/lib/libc-2.17.so") or os.path.isfile("/lib64/libc-2.17.so")) and os.path.isdir("/opt/python"): # Same sloppy check for manylinux2014. - if GetTargetArch() in ('x86_64', 'amd64'): + if target_arch in ('x86_64', 'amd64'): PLATFORM = 'manylinux2014-x86_64' - elif GetTargetArch() in ('arm64', 'aarch64'): + elif target_arch in ('arm64', 'aarch64'): PLATFORM = 'manylinux2014-aarch64' else: PLATFORM = 'manylinux2014-i686' elif target == 'linux' and (os.path.isfile("/lib/i386-linux-gnu/libc-2.24.so") or os.path.isfile("/lib/x86_64-linux-gnu/libc-2.24.so")) and os.path.isdir("/opt/python"): # Same sloppy check for manylinux_2_24. - if GetTargetArch() in ('x86_64', 'amd64'): + if target_arch in ('x86_64', 'amd64'): PLATFORM = 'manylinux_2_24-x86_64' - elif GetTargetArch() in ('arm64', 'aarch64'): + elif target_arch in ('arm64', 'aarch64'): PLATFORM = 'manylinux_2_24-aarch64' else: PLATFORM = 'manylinux_2_24-i686' +elif target == 'linux' and os.path.isfile("/lib64/libc-2.28.so") and os.path.isfile('/etc/almalinux-release') and os.path.isdir("/opt/python"): + # Same sloppy check for manylinux_2_28. + if target_arch in ('x86_64', 'amd64'): + PLATFORM = 'manylinux_2_28-x86_64' + elif target_arch in ('arm64', 'aarch64'): + PLATFORM = 'manylinux_2_28-aarch64' + else: + raise RuntimeError('Unhandled arch %s, please file a bug report!' % (target_arch)) + elif not CrossCompiling(): if HasTargetArch(): # Replace the architecture in the platform string. platform_parts = get_platform().rsplit('-', 1) - target_arch = GetTargetArch() if target_arch == 'amd64': target_arch = 'x86_64' PLATFORM = platform_parts[0] + '-' + target_arch @@ -529,7 +538,6 @@ elif not CrossCompiling(): PLATFORM = get_platform() else: - target_arch = GetTargetArch() if target_arch == 'amd64': target_arch = 'x86_64' PLATFORM = '{0}-{1}'.format(target, target_arch) diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index f7ab00a0f9..2f18789e78 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -560,6 +560,8 @@ def makewheel(version, output_dir, platform=None): platform = platform.replace("linux", "manylinux2014") elif os.path.isfile("/lib/i386-linux-gnu/libc-2.24.so") or os.path.isfile("/lib/x86_64-linux-gnu/libc-2.24.so"): platform = platform.replace("linux", "manylinux_2_24") + elif os.path.isfile("/lib64/libc-2.28.so") and os.path.isfile('/etc/almalinux-release'): + platform = platform.replace("linux", "manylinux_2_28") platform = platform.replace('-', '_').replace('.', '_') From ecbd262ac47aa09e65725af30ae077f8e1b6996e Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 14:43:47 +0100 Subject: [PATCH 08/15] dist: Always use manylinux2014 for Python 3.11+, add manylinux_2_28 --- direct/src/dist/commands.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 02e2285606..d36d95f374 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -233,7 +233,10 @@ class build_apps(setuptools.Command): 'macosx_10_6_x86_64', 'win_amd64', ] - if sys.version_info >= (3, 10): + if sys.version_info >= (3, 11): + # manylinux2010 is not offered for Python 3.11 anymore + self.platforms[0] = 'manylinux2014_x86_64' + elif sys.version_info >= (3, 10): # manylinux1 is not offered for Python 3.10 anymore self.platforms[0] = 'manylinux2010_x86_64' if sys.version_info >= (3, 8): @@ -1440,6 +1443,10 @@ class bdist_apps(setuptools.Command): 'manylinux_2_24_ppc64': ['gztar'], 'manylinux_2_24_ppc64le': ['gztar'], 'manylinux_2_24_s390x': ['gztar'], + 'manylinux_2_28_x86_64': ['gztar'], + 'manylinux_2_28_aarch64': ['gztar'], + 'manylinux_2_28_ppc64le': ['gztar'], + 'manylinux_2_28_s390x': ['gztar'], # Everything else defaults to ['zip'] } From ffbfdb22e0a13ec1d5ec4a12f79432c9d650be5b Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 14:45:49 +0100 Subject: [PATCH 09/15] dist: Add `prefer_discrete_gpu` option to force use of dedicated GPU Currently only implemented on Windows. Fixes #680 --- direct/src/dist/commands.py | 12 +++++++--- direct/src/dist/pefile.py | 30 +++++++++++++++++++++++++ pandatool/src/deploy-stub/deploy-stub.c | 7 ++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index d36d95f374..0cae76631b 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -250,6 +250,7 @@ class build_apps(setuptools.Command): self.log_filename = None self.log_filename_strftime = False self.log_append = False + self.prefer_discrete_gpu = False self.requirements_path = os.path.join(os.getcwd(), 'requirements.txt') self.use_optimized_wheels = True self.optimized_wheel_index = '' @@ -516,11 +517,16 @@ class build_apps(setuptools.Command): self.icon_objects.get('*', None), ) - if icon is not None: + if icon is not None or self.prefer_discrete_gpu: pef = pefile.PEFile() pef.open(runtime, 'r+') - pef.add_icon(icon) - pef.add_resource_section() + if icon is not None: + pef.add_icon(icon) + pef.add_resource_section() + if self.prefer_discrete_gpu: + if not pef.rename_export("SymbolPlaceholder___________________", "AmdPowerXpressRequestHighPerformance") or \ + not pef.rename_export("SymbolPlaceholder__", "NvOptimusEnablement"): + self.warn("Failed to apply prefer_discrete_gpu, newer target Panda3D version may be required") pef.write_changes() pef.close() diff --git a/direct/src/dist/pefile.py b/direct/src/dist/pefile.py index df7aac8432..2a98f7f0ce 100755 --- a/direct/src/dist/pefile.py +++ b/direct/src/dist/pefile.py @@ -605,6 +605,36 @@ class PEFile(object): if self.res_rva.addr and self.res_rva.size: self.resources.unpack_from(self.vmem, self.res_rva.addr) + def _mark_address_modified(self, rva): + for section in self.sections: + if rva >= section.vaddr and rva - section.vaddr <= section.size: + section.modified = True + + def rename_export(self, old_name, new_name): + """ Renames a symbol in the export table. """ + + assert len(new_name) <= len(old_name) + + new_name = new_name.ljust(len(old_name) + 1, '\0').encode('ascii') + + start = self.exp_rva.addr + expdir = expdirtab(*unpack(' From 32ebe11b06aac6babf41ae4e7a1e64c86b6b64f2 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 15:21:39 +0100 Subject: [PATCH 10/15] dist: Add an option to retain docstrings in compiled Python code Fixes #1341 --- direct/src/dist/FreezeTool.py | 39 ++++++++++++++++++++----- direct/src/dist/commands.py | 5 +++- pandatool/src/deploy-stub/deploy-stub.c | 7 ++++- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/direct/src/dist/FreezeTool.py b/direct/src/dist/FreezeTool.py index db7ac1092c..7e77acdb4c 100644 --- a/direct/src/dist/FreezeTool.py +++ b/direct/src/dist/FreezeTool.py @@ -794,7 +794,7 @@ class Freezer: return 'ModuleDef(%s)' % (', '.join(args)) def __init__(self, previous = None, debugLevel = 0, - platform = None, path=None): + platform = None, path=None, optimize=None): # Normally, we are freezing for our own platform. Change this # if untrue. self.platform = platform or PandaSystem.getPlatform() @@ -859,6 +859,11 @@ class Freezer: self.mf = None + if optimize is None or optimize < 0: + self.optimize = sys.flags.optimize + else: + self.optimize = optimize + # Actually, make sure we know how to find all of the # already-imported modules. (Some of them might do their own # special path mangling.) @@ -1174,7 +1179,7 @@ class Freezer: else: includes.append(mdef) - self.mf = PandaModuleFinder(excludes=list(excludeDict.keys()), suffixes=self.moduleSuffixes, path=self.path) + self.mf = PandaModuleFinder(excludes=list(excludeDict.keys()), suffixes=self.moduleSuffixes, path=self.path, optimize=self.optimize) # Attempt to import the explicit modules into the modulefinder. @@ -1445,7 +1450,10 @@ class Freezer: else: filename += '.pyo' if multifile.findSubfile(filename) < 0: - code = compile('', moduleName, 'exec') + if sys.version_info >= (3, 2): + code = compile('', moduleName, 'exec', optimize=self.optimize) + else: + code = compile('', moduleName, 'exec') self.__addPyc(multifile, filename, code, compressionLevel) moduleDirs[str] = True @@ -1525,7 +1533,10 @@ class Freezer: source = open(sourceFilename.toOsSpecific(), 'r').read() if source and source[-1] != '\n': source = source + '\n' - code = compile(source, str(sourceFilename), 'exec') + if sys.version_info >= (3, 2): + code = compile(source, str(sourceFilename), 'exec', optimize=self.optimize) + else: + code = compile(source, str(sourceFilename), 'exec') self.__addPyc(multifile, filename, code, compressionLevel) @@ -1604,7 +1615,10 @@ class Freezer: # trouble importing it as a builtin module. Synthesize a frozen # module that loads it as builtin. if '.' in moduleName and self.linkExtensionModules: - code = compile('import sys;del sys.modules["%s"];import imp;imp.init_builtin("%s")' % (moduleName, moduleName), moduleName, 'exec') + if sys.version_info >= (3, 2): + code = compile('import sys;del sys.modules["%s"];import imp;imp.init_builtin("%s")' % (moduleName, moduleName), moduleName, 'exec', optimize=self.optimize) + else: + code = compile('import sys;del sys.modules["%s"];import imp;imp.init_builtin("%s")' % (moduleName, moduleName), moduleName, 'exec') code = marshal.dumps(code) mangledName = self.mangleName(moduleName) moduleDefs.append(self.makeModuleDef(mangledName, code)) @@ -1881,7 +1895,7 @@ class Freezer: else: code = 'import sys;del sys.modules["%s"];import sys,os,imp;imp.load_dynamic("%s",os.path.join(os.path.dirname(sys.executable), "%s%s"))' % (moduleName, moduleName, moduleName, modext) if sys.version_info >= (3, 2): - code = compile(code, moduleName, 'exec', optimize=2) + code = compile(code, moduleName, 'exec', optimize=self.optimize) else: code = compile(code, moduleName, 'exec') code = marshal.dumps(code) @@ -1969,6 +1983,8 @@ class Freezer: flags |= 1 if log_filename_strftime: flags |= 2 + if self.optimize < 2: + flags |= 4 # keep_docstrings # Compose the header we will be writing to the stub, to tell it # where to find the module data blob, as well as other variables. @@ -2341,6 +2357,7 @@ class PandaModuleFinder(modulefinder.ModuleFinder): """ self.suffixes = kw.pop('suffixes', imp.get_suffixes()) + self.optimize = kw.pop('optimize', -1) modulefinder.ModuleFinder.__init__(self, *args, **kw) @@ -2446,7 +2463,10 @@ class PandaModuleFinder(modulefinder.ModuleFinder): if type is _PKG_NAMESPACE_DIRECTORY: m = self.add_module(fqname) - m.__code__ = compile('', '', 'exec') + if sys.version_info >= (3, 2): + m.__code__ = compile('', '', 'exec', optimize=self.optimize) + else: + m.__code__ = compile('', '', 'exec') m.__path__ = pathname return m @@ -2458,7 +2478,10 @@ class PandaModuleFinder(modulefinder.ModuleFinder): code = fp.read() code += b'\n' if isinstance(code, bytes) else '\n' - co = compile(code, pathname, 'exec') + if sys.version_info >= (3, 2): + co = compile(code, pathname, 'exec', optimize=self.optimize) + else: + co = compile(code, pathname, 'exec') elif type == imp.PY_COMPILED: if sys.version_info >= (3, 7): try: diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 0cae76631b..8bc943232b 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -252,6 +252,7 @@ class build_apps(setuptools.Command): self.log_append = False self.prefer_discrete_gpu = False self.requirements_path = os.path.join(os.getcwd(), 'requirements.txt') + self.strip_docstrings = True self.use_optimized_wheels = True self.optimized_wheel_index = '' self.pypi_extra_indexes = [ @@ -776,7 +777,9 @@ class build_apps(setuptools.Command): # Legacy handling for Tcl data files site_py += SITE_PY_TKINTER_ADDENDUM - freezer = FreezeTool.Freezer(platform=platform, path=path) + optimize = 2 if self.strip_docstrings else 1 + + freezer = FreezeTool.Freezer(platform=platform, path=path, optimize=optimize) freezer.addModule('__main__', filename=mainscript) freezer.addModule('site', filename='site.py', text=site_py) for incmod in self.include_modules.get(appname, []) + self.include_modules.get('*', []): diff --git a/pandatool/src/deploy-stub/deploy-stub.c b/pandatool/src/deploy-stub/deploy-stub.c index 26cc480c9d..b0251be473 100644 --- a/pandatool/src/deploy-stub/deploy-stub.c +++ b/pandatool/src/deploy-stub/deploy-stub.c @@ -40,6 +40,7 @@ enum Flags { F_log_append = 1, F_log_filename_strftime = 2, + F_keep_docstrings = 4, }; /* Define an exposed symbol where we store the offset to the module data. */ @@ -449,7 +450,11 @@ int Py_FrozenMain(int argc, char **argv) Py_NoUserSiteDirectory = 1; #if PY_VERSION_HEX >= 0x03020000 - Py_OptimizeFlag = 2; + if (blobinfo.flags & F_keep_docstrings) { + Py_OptimizeFlag = 1; + } else { + Py_OptimizeFlag = 2; + } #endif #ifndef NDEBUG From 45ac5029c00209aacbbbed88d311d0033c21034b Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 16:53:51 +0100 Subject: [PATCH 11/15] glgsg: Fix compile error with OpenGL ES 1 Introduced by 2c9deaaaf06fba7b4d5f71e9e75cd4919aa5a18e --- panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 3e22c98eb3..1b0190ab93 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -11623,6 +11623,9 @@ set_state_and_transform(const RenderState *target, if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) || !_state_mask.get_bit(texture_slot)) { PStatGPUTimer timer(this, _draw_set_state_texture_pcollector); +#ifdef OPENGLES_1 + determine_target_texture(); +#else if (has_fixed_function_pipeline() || _current_shader == nullptr || _current_shader == _default_shader) { @@ -11634,6 +11637,7 @@ set_state_and_transform(const RenderState *target, _target_tex_gen = (const TexGenAttrib *) _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()); } +#endif do_issue_texture(); // Since the TexGen and TexMatrix states depend partly on the particular From 619050bb32a6b154e48af968ca9372278292cd61 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 16:56:02 +0100 Subject: [PATCH 12/15] cocoadisplay: Fix fullscreen issues on M1 macs The OpenGL-on-Metal drivers used on these machines don't support CGLSetFullScreenOnDisplay, so we need to disable it on those machines. This also applies when running a x86_64 app through Rosetta 2, hence the sysctlbyname check. Furthermore, we need to set the appropriate shielding level, which need not be `NSMainMenuWindowLevel+1`. Fixes #1316 Co-authored-by: LD --- panda/src/cocoadisplay/cocoaGraphicsWindow.mm | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index ea48bb8c79..044329608c 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -43,12 +43,35 @@ #import #import +#include + TypeHandle CocoaGraphicsWindow::_type_handle; #ifndef MAC_OS_X_VERSION_10_15 #define NSAppKitVersionNumber10_14 1671 #endif +/** + * Returns true if this is an arm64-based mac. + */ +static int is_arm64_mac() { +#ifdef __aarch64__ + return 1; +#elif defined(__x86_64__) + // Running in Rosetta 2? + static int ret = -1; + if (ret < 0) { + size_t size = sizeof(ret); + if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) == -1) { + ret = 0; + } + } + return ret; +#else + return 0; +#endif +} + /** * */ @@ -189,8 +212,17 @@ begin_frame(FrameMode mode, Thread *current_thread) { // Set the drawable. if (_properties.get_fullscreen()) { - // Fullscreen. - CGLSetFullScreenOnDisplay((CGLContextObj) [cocoagsg->_context CGLContextObj], CGDisplayIDToOpenGLDisplayMask(_display)); + // Fullscreen. Note that this call doesn't work with the newer + // Metal-based OpenGL drivers. + if (!is_arm64_mac()) { + CGLError err = CGLSetFullScreenOnDisplay((CGLContextObj) [cocoagsg->_context CGLContextObj], CGDisplayIDToOpenGLDisplayMask(_display)); + if (err != kCGLNoError) { + cocoadisplay_cat.error() + << "Failed call to CGLSetFullScreenOnDisplay with display mask " + << CGDisplayIDToOpenGLDisplayMask(_display) << ": " << CGLErrorString(err) << "\n"; + return false; + } + } } else { // Although not recommended, it is technically possible to use the same // context with multiple different-sized windows. If that happens, the @@ -626,7 +658,7 @@ open_window() { } if (_properties.get_fullscreen()) { - [_window setLevel: NSMainMenuWindowLevel + 1]; + [_window setLevel: CGShieldingWindowLevel()]; } else { switch (_properties.get_z_order()) { case WindowProperties::Z_bottom: @@ -859,7 +891,7 @@ set_properties_now(WindowProperties &properties) { [_window setStyleMask:NSBorderlessWindowMask]; } [_window makeFirstResponder:_view]; - [_window setLevel:NSMainMenuWindowLevel+1]; + [_window setLevel:CGShieldingWindowLevel()]; [_window makeKeyAndOrderFront:nil]; } @@ -898,7 +930,7 @@ set_properties_now(WindowProperties &properties) { [_window setStyleMask:NSBorderlessWindowMask]; } [_window makeFirstResponder:_view]; - [_window setLevel:NSMainMenuWindowLevel+1]; + [_window setLevel:CGShieldingWindowLevel()]; [_window makeKeyAndOrderFront:nil]; } From 27d3aed2d327e4bfedae48d855da6c04c056f30e Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 17:30:26 +0100 Subject: [PATCH 13/15] makepanda: Fix detection issues with newer macOS/XCode versions --- makepanda/makepandacore.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 56493f576e..ad75ae6f1d 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -2258,6 +2258,10 @@ def SdkLocatePython(prefer_thirdparty_python=False): # Fall back to looking on the system. py_fwx = "/Library/Frameworks/Python.framework/Versions/" + version + if not os.path.exists(py_fwx): + # Newer macOS versions use this scheme. + py_fwx = "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/" + version + if not os.path.exists(py_fwx): exit("Could not locate Python installation at %s" % (py_fwx)) @@ -2503,6 +2507,10 @@ def SdkLocateMacOSX(osxtarget = None, archs = []): SDK["MACOSX"] = "/Library/Developer/CommandLineTools/SDKs/MacOSX11.1.sdk" elif sdkname == "MacOSX11.0" and os.path.exists("/Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk"): SDK["MACOSX"] = "/Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk" + elif sdkname == "MacOSX11.0" and os.path.exists("/Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk"): + SDK["MACOSX"] = "/Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk" + elif sdkname == "MacOSX11.0" and os.path.exists("/Library/Developer/CommandLineTools/SDKs/MacOSX13.0.sdk"): + SDK["MACOSX"] = "/Library/Developer/CommandLineTools/SDKs/MacOSX13.0.sdk" else: exit("Couldn't find any MacOSX SDK for macOS version %s!" % sdkname) SDK["OSXTARGET"] = osxtarget From 765d76740db188746b49f3e1d3011f536a9e3c1c Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 19:37:38 +0100 Subject: [PATCH 14/15] dist: Use manylinux2014_x86_64 for linux_x86_64 alias on Py 3.11 --- direct/src/dist/commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 8bc943232b..0a6beff5c5 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -488,7 +488,9 @@ class build_apps(setuptools.Command): if platform.startswith('linux_'): # Also accept manylinux. arch = platform[6:] - if sys.version_info >= (3, 10): + if sys.version_info >= (3, 11): + pip_args += ['--platform', 'manylinux2014_' + arch] + elif sys.version_info >= (3, 10): pip_args += ['--platform', 'manylinux2010_' + arch] else: pip_args += ['--platform', 'manylinux1_' + arch] From 3f3fd74f869b21b249e76d3068cb1735afa807ae Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 6 Dec 2022 19:38:37 +0100 Subject: [PATCH 15/15] dist: Use Panda loader system for converting models to .bam Set bam_model_extensions in order to specify which formats are automatically converted to .bam Fixes #714 --- direct/src/dist/commands.py | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 0a6beff5c5..44243ee8b7 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -67,6 +67,44 @@ def _parse_dict(input): return d +def _register_python_loaders(): + # We need this method so that we don't depend on direct.showbase.Loader. + if getattr(_register_python_loaders, 'done', None): + return + + _register_python_loaders.done = True + + try: + import pkg_resources + except ImportError: + return + + registry = p3d.LoaderFileTypeRegistry.getGlobalPtr() + + for entry_point in pkg_resources.iter_entry_points('panda3d.loaders'): + registry.register_deferred_type(entry_point) + + +def _model_to_bam(_build_cmd, srcpath, dstpath): + if dstpath.endswith('.gz') or dstpath.endswith('.pz'): + dstpath = dstpath[:-3] + dstpath = dstpath + '.bam' + + src_fn = p3d.Filename.from_os_specific(srcpath) + dst_fn = p3d.Filename.from_os_specific(dstpath) + + _register_python_loaders() + + loader = p3d.Loader.get_global_ptr() + options = p3d.LoaderOptions(p3d.LoaderOptions.LF_report_errors | + p3d.LoaderOptions.LF_no_ram_cache) + node = loader.load_sync(src_fn, options) + if not node: + raise IOError('Failed to load model: %s' % (srcpath)) + + if not p3d.NodePath(node).write_bam_file(dst_fn): + raise IOError('Failed to write .bam file: %s' % (dstpath)) + def egg2bam(_build_cmd, srcpath, dstpath): if dstpath.endswith('.gz') or dstpath.endswith('.pz'): @@ -259,6 +297,7 @@ class build_apps(setuptools.Command): 'https://archive.panda3d.org/thirdparty', ] self.file_handlers = {} + self.bam_model_extensions = [] self.exclude_dependencies = [ # Windows 'kernel32.dll', 'user32.dll', 'wsock32.dll', 'ws2_32.dll', @@ -414,6 +453,15 @@ class build_apps(setuptools.Command): for glob in self.exclude_dependencies: glob.case_sensitive = False + # bam_model_extensions registers a 2bam handler for each given extension. + # They can override a default handler, but not a custom handler. + if self.bam_model_extensions: + for ext in self.bam_model_extensions: + ext = '.' + ext.lstrip('.') + assert ext not in self.file_handlers, \ + 'Extension {} occurs in both file_handlers and bam_model_extensions!'.format(ext) + self.file_handlers[ext] = _model_to_bam + tmp = self.default_file_handlers.copy() tmp.update(self.file_handlers) self.file_handlers = tmp