Merge branch 'release/1.10.x'

This commit is contained in:
rdb 2022-12-06 19:56:07 +01:00
commit c82f95ad6b
15 changed files with 226 additions and 41 deletions

View File

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

View File

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

View File

@ -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+')
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']
}

View File

@ -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('<IIHHIIIIIII', self.vmem[start:start+40]))
if expdir.nnames == 0 or expdir.ordinals == 0 or expdir.names == 0:
return False
nptr = expdir.names
for i in range(expdir.nnames):
name_rva, = unpack('<I', self.vmem[nptr:nptr+4])
if name_rva != 0:
name = _unpack_zstring(self.vmem, name_rva)
if name == old_name:
self.vmem[name_rva:name_rva+len(new_name)] = new_name
self._mark_address_modified(name_rva)
return True
nptr += 4
return False
def get_export_address(self, symbol_name):
""" Finds the virtual address for a named export symbol. """

View File

@ -180,3 +180,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

View File

@ -226,6 +226,17 @@ __bool__() const {
return !get_value().empty();
}
/**
* 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

View File

@ -61,6 +61,7 @@ PUBLISHED:
INLINE void set_word(size_t n, const Filename &value);
INLINE bool __bool__() const;
INLINE std::wstring __fspath__() const;
private:
void reload_cache();

View File

@ -382,8 +382,9 @@ MAJOR_VERSION = '.'.join(VERSION.split('.')[:2])
# 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'
@ -391,7 +392,7 @@ if target == 'windows':
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')):
@ -416,45 +417,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
@ -463,7 +472,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)

View File

@ -2203,6 +2203,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))
@ -2439,7 +2443,7 @@ def SdkLocateMacOSX(archs = []):
# Prefer pre-10.14 for now so that we can keep building FMOD.
sdk_versions += ["10.13", "10.12", "10.11", "10.10", "10.9"]
sdk_versions += ["11.3", "11.1", "11.0"]
sdk_versions += ["13.0", "12.3", "11.3", "11.1", "11.0"]
if 'arm64' not in archs:
sdk_versions += ["10.15", "10.14"]

View File

@ -656,6 +656,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('.', '_')

View File

@ -43,12 +43,35 @@
#import <OpenGL/OpenGL.h>
#import <Carbon/Carbon.h>
#include <sys/sysctl.h>
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];
}

View File

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

View File

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

View File

@ -1739,7 +1739,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if (_lost_keypresses) {
resend_lost_keypresses();
}
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();
}
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();
}
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();
}
if (wparam == 0) {
ReleaseCapture();
}
int whichButton = GET_XBUTTON_WPARAM(wparam);
if (whichButton == XBUTTON1) {
_input->button_up(MouseButton::button(3), get_message_time());

View File

@ -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 <windows.h>
@ -389,7 +397,11 @@ int Py_FrozenMain(int argc, char **argv)
Py_NoUserSiteDirectory = 1;
#if PY_VERSION_HEX >= 0x03020000
if (blobinfo.flags & F_keep_docstrings) {
Py_OptimizeFlag = 1;
} else {
Py_OptimizeFlag = 2;
}
#endif
#ifndef NDEBUG