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 diff --git a/direct/src/dist/FreezeTool.py b/direct/src/dist/FreezeTool.py index 37583e9e12..0dfe2977d8 100644 --- a/direct/src/dist/FreezeTool.py +++ b/direct/src/dist/FreezeTool.py @@ -787,7 +787,7 @@ class Freezer: return 'ModuleDef(%s)' % (', '.join(args)) def __init__(self, previous = None, debugLevel = 0, - platform = None, path=None, hiddenImports=None): + platform = None, path=None, hiddenImports=None, optimize=None): # Normally, we are freezing for our own platform. Change this # if untrue. self.platform = platform or PandaSystem.getPlatform() @@ -917,7 +917,13 @@ class Freezer: ('.so', 'rb', 3), ] - self.mf = PandaModuleFinder(excludes=['doctest'], suffixes=suffixes, path=path) + if optimize is None or optimize < 0: + self.optimize = sys.flags.optimize + else: + self.optimize = optimize + + self.mf = PandaModuleFinder(excludes=['doctest'], suffixes=suffixes, + path=path, optimize=self.optimize) def excludeFrom(self, freezer): """ Excludes all modules that have already been processed by @@ -1413,7 +1419,7 @@ class Freezer: else: filename += '.pyo' if multifile.findSubfile(filename) < 0: - code = compile('', moduleName, 'exec', optimize=2) + code = compile('', moduleName, 'exec', optimize=self.optimize) self.__addPyc(multifile, filename, code, compressionLevel) moduleDirs[str] = True @@ -1493,7 +1499,7 @@ class Freezer: source = open(sourceFilename.toOsSpecific(), 'r').read() if source and source[-1] != '\n': source = source + '\n' - code = compile(source, str(sourceFilename), 'exec', optimize=2) + code = compile(source, str(sourceFilename), 'exec', optimize=self.optimize) self.__addPyc(multifile, filename, code, compressionLevel) @@ -1572,7 +1578,7 @@ 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', optimize=2) + code = compile('import sys;del sys.modules["%s"];import imp;imp.init_builtin("%s")' % (moduleName, moduleName), moduleName, 'exec', optimize=self.optimize) code = marshal.dumps(code) mangledName = self.mangleName(moduleName) moduleDefs.append(self.makeModuleDef(mangledName, code)) @@ -1845,7 +1851,7 @@ class Freezer: code = 'import sys;del sys.modules["%s"];import sys,os,imp;imp.load_dynamic("%s",os.path.join(sys.path[0], "%s%s"))' % (moduleName, moduleName, moduleName, modext) 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) - code = compile(code, moduleName, 'exec', optimize=2) + code = compile(code, moduleName, 'exec', optimize=self.optimize) code = marshal.dumps(code) moduleList.append((moduleName, len(pool), len(code))) pool += code @@ -1946,6 +1952,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. @@ -2377,6 +2385,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) @@ -2530,7 +2539,7 @@ class PandaModuleFinder(modulefinder.ModuleFinder): if type is _PKG_NAMESPACE_DIRECTORY: m = self.add_module(fqname) - m.__code__ = compile('', '', 'exec', optimize=2) + m.__code__ = compile('', '', 'exec', optimize=self.optimize) m.__path__ = pathname return m @@ -2542,7 +2551,7 @@ class PandaModuleFinder(modulefinder.ModuleFinder): code = fp.read() code += b'\n' if isinstance(code, bytes) else '\n' - co = compile(code, pathname, 'exec', optimize=2) + co = compile(code, pathname, 'exec', optimize=self.optimize) 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 323d11b255..b5da8c78c9 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -49,6 +49,39 @@ 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 + + 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'): @@ -277,13 +310,16 @@ class build_apps(setuptools.Command): self.log_filename = None self.log_filename_strftime = True 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 = [ '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', @@ -444,6 +480,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 @@ -625,11 +670,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() @@ -944,7 +994,8 @@ class build_apps(setuptools.Command): freezer = FreezeTool.Freezer( platform=platform, path=path, - hiddenImports=self.hidden_imports + hiddenImports=self.hidden_imports, + optimize=2 if self.strip_docstrings else 1 ) freezer.addModule('__main__', filename=mainscript) if platform.startswith('android'): @@ -1617,6 +1668,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'], 'android': ['aab'], # Everything else defaults to ['zip'] } diff --git a/direct/src/dist/pefile.py b/direct/src/dist/pefile.py index 002c758d2d..b72f62e7c1 100755 --- a/direct/src/dist/pefile.py +++ b/direct/src/dist/pefile.py @@ -600,6 +600,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(' #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 +} + /** * */ @@ -187,8 +210,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: @@ -824,7 +856,7 @@ set_properties_now(WindowProperties &properties) { [_window setStyleMask:NSBorderlessWindowMask]; } [_window makeFirstResponder:_view]; - [_window setLevel:NSMainMenuWindowLevel+1]; + [_window setLevel:CGShieldingWindowLevel()]; [_window makeKeyAndOrderFront:nil]; } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 5cea01b782..95078a71e2 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -12078,7 +12078,21 @@ 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) { + 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()); + } +#endif do_issue_texture(); // Since the TexGen and TexMatrix states depend partly on the particular diff --git a/panda/src/tform/mouseWatcher.cxx b/panda/src/tform/mouseWatcher.cxx index 3b63380548..fff2666d2c 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; } } diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 93b4ba989a..9b5827a0a1 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -1739,7 +1739,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; @@ -1747,7 +1749,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; @@ -1755,7 +1759,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; @@ -1764,7 +1770,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()); diff --git a/pandatool/src/deploy-stub/deploy-stub.c b/pandatool/src/deploy-stub/deploy-stub.c index 3d3ba9c9c1..c021e3b7fb 100644 --- a/pandatool/src/deploy-stub/deploy-stub.c +++ b/pandatool/src/deploy-stub/deploy-stub.c @@ -34,6 +34,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. */ @@ -56,6 +57,13 @@ volatile struct { // end up putting it in the .bss section for zero-initialized data. } blobinfo = {(uint64_t)-1}; + +#ifdef _WIN32 +// These placeholders can have their names changed by deploy-stub. +__declspec(dllexport) DWORD SymbolPlaceholder___________________ = 0x00000001; +__declspec(dllexport) DWORD SymbolPlaceholder__ = 0x00000001; +#endif + #ifdef MS_WINDOWS # define WIN32_LEAN_AND_MEAN # include @@ -389,7 +397,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