From ac85b054004ed52d90476b64a26f5387ea46e61e Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 25 Dec 2019 16:32:19 +0100 Subject: [PATCH 01/23] py_compat: fix _PyObject_CallNoArg in Python 3.5 --- dtool/src/interrogatedb/py_compat.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/dtool/src/interrogatedb/py_compat.h b/dtool/src/interrogatedb/py_compat.h index a0d52c7fdc..5d0f3bf4ea 100644 --- a/dtool/src/interrogatedb/py_compat.h +++ b/dtool/src/interrogatedb/py_compat.h @@ -141,16 +141,13 @@ typedef long Py_hash_t; #if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_CallNoArg) INLINE PyObject *_PyObject_CallNoArg(PyObject *func) { - static PyTupleObject empty_tuple = {PyVarObject_HEAD_INIT(nullptr, 0)}; -#ifdef Py_TRACE_REFS - _Py_AddToAllObjects((PyObject *)&empty_tuple, 0); -#endif - return PyObject_Call(func, (PyObject *)&empty_tuple, nullptr); + static PyObject *empty_tuple = PyTuple_New(0); + return PyObject_Call(func, empty_tuple, nullptr); } # define _PyObject_CallNoArg _PyObject_CallNoArg #endif -#ifndef _PyObject_FastCall +#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_FastCall) INLINE PyObject *_PyObject_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs) { PyObject *tuple = PyTuple_New(nargs); for (Py_ssize_t i = 0; i < nargs; ++i) { From cb53e5d8220699da17cf802af6e2fb4b6add7815 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 25 Dec 2019 16:57:06 +0100 Subject: [PATCH 02/23] dcparser: fix unpacking uint64 and int64 Closes #751 --- direct/src/dcparser/dcPackerInterface.I | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/direct/src/dcparser/dcPackerInterface.I b/direct/src/dcparser/dcPackerInterface.I index 160cc4fdd9..c9daac2c7e 100644 --- a/direct/src/dcparser/dcPackerInterface.I +++ b/direct/src/dcparser/dcPackerInterface.I @@ -253,8 +253,9 @@ do_unpack_int64(const char *buffer) { ((uint64_t)(unsigned char)buffer[4] << 32) | ((uint64_t)(unsigned char)buffer[5] << 40) | ((uint64_t)(unsigned char)buffer[6] << 48) | - ((int64_t)(signed char)buffer[7] << 54)); + ((int64_t)(signed char)buffer[7] << 56)); } + /** * */ @@ -295,10 +296,9 @@ do_unpack_uint64(const char *buffer) { ((uint64_t)(unsigned char)buffer[4] << 32) | ((uint64_t)(unsigned char)buffer[5] << 40) | ((uint64_t)(unsigned char)buffer[6] << 48) | - ((int64_t)(signed char)buffer[7] << 54)); + ((uint64_t)(unsigned char)buffer[7] << 56)); } - /** * */ From b9713f71b1a336f7f9639c1e48c6972c2242c6f2 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 25 Dec 2019 16:58:11 +0100 Subject: [PATCH 03/23] tests: add some DCPacker unit tests (for #751) --- tests/dcparser/test_dcpacker.py | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/dcparser/test_dcpacker.py diff --git a/tests/dcparser/test_dcpacker.py b/tests/dcparser/test_dcpacker.py new file mode 100644 index 0000000000..9bf8e5252e --- /dev/null +++ b/tests/dcparser/test_dcpacker.py @@ -0,0 +1,36 @@ +import pytest + +direct = pytest.importorskip("panda3d.direct") + + +def test_pack_int8(): + for num in range(-128, 128): + packer = direct.DCPacker() + packer.raw_pack_int8(num) + packer.set_unpack_data(packer.get_bytes()) + assert packer.raw_unpack_int8() == num + + +def test_pack_uint8(): + for num in range(256): + packer = direct.DCPacker() + packer.raw_pack_uint8(num) + packer.set_unpack_data(packer.get_bytes()) + assert packer.raw_unpack_uint8() == num + + +def test_pack_int64(): + for num in (0, -1, 0x7fffffff, -0x80000000, 0x7fffffffffffffff, 0x7ffffffffffffffe, -0x8000000000000000, -0x7fffffffffffffff): + packer = direct.DCPacker() + packer.raw_pack_int64(num) + packer.set_unpack_data(packer.get_bytes()) + assert packer.raw_unpack_int64() == num + + +def test_pack_uint64(): + for num in (0, 1, 0x7fffffff, 0xffffffff, 0x7fffffffffffffff, 0xfffffffffffffffe, 0xffffffffffffffff): + packer = direct.DCPacker() + packer.raw_pack_uint64(num) + packer.set_unpack_data(packer.get_bytes()) + assert packer.raw_unpack_uint64() == num + From b656b0bbf9866311eadd9f3944edab18969e0eed Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 18:01:51 +0100 Subject: [PATCH 04/23] dxgsg9: recreate vertex buffer if size was modified Fixes #824 --- panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index e39e246841..f14cf1788d 100644 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -496,6 +496,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) { } #endif + dvbc->update_data_size_bytes(num_bytes); return dvbc; } else { dxgsg9_cat.error() @@ -533,14 +534,42 @@ apply_vertex_buffer(VertexBufferContext *vbc, return false; } - PStatTimer timer(_load_vertex_buffer_pcollector, reader->get_current_thread()); - #if 0 if (dvbc->changed_size(reader)) { - // We have to destroy the old vertex buffer and create a new one. - dvbc->create_vbuffer(*_screen, reader); + // Destroy and recreate the buffer. + if (dvbc->_vbuffer != nullptr) { + dvbc->_vbuffer->Release(); + dvbc->_vbuffer = nullptr; + } + + DWORD usage; + D3DPOOL pool; + if (_screen->_managed_vertex_buffers) { + pool = D3DPOOL_MANAGED; + usage = D3DUSAGE_WRITEONLY; + } else { + pool = D3DPOOL_DEFAULT; + usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC; + } + + PStatTimer timer(_create_vertex_buffer_pcollector, Thread::get_current_thread()); + + HRESULT hr; + int attempts = 0; + do { + hr = _screen->_d3d_device->CreateVertexBuffer(num_bytes, usage, dvbc->_fvf, pool, &dvbc->_vbuffer, nullptr); + attempts++; + } while (check_dx_allocation(hr, num_bytes, attempts)); + + if (FAILED(hr)) { + dvbc->_vbuffer = nullptr; + dxgsg9_cat.error() + << "CreateVertexBuffer failed" << D3DERRORSTRING(hr); + return false; + } } - #endif + + PStatTimer timer(_load_vertex_buffer_pcollector, reader->get_current_thread()); HRESULT hr; BYTE *local_pointer; From e13719132b1aefcd6c81f8303e5aebd8d283143d Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 18:04:55 +0100 Subject: [PATCH 05/23] dxgsg9: don't attempt to restore gamma if it wasn't modified --- panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index f14cf1788d..ca3fb07d79 100644 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -5269,6 +5269,7 @@ calc_fb_properties(DWORD cformat, DWORD dformat, #define GAMMA_1 (255.0 * 256.0) static bool _gamma_table_initialized = false; +static bool _gamma_changed = false; static unsigned short _original_gamma_table [256 * 3]; void _create_gamma_table_dx9 (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) { @@ -5366,6 +5367,7 @@ static_set_gamma(bool restore, PN_stdfloat gamma) { if (SetDeviceGammaRamp (hdc, ramp)) { set = true; + _gamma_changed = !restore; } ReleaseDC (nullptr, hdc); @@ -5403,7 +5405,9 @@ restore_gamma() { void DXGraphicsStateGuardian9:: atexit_function(void) { set_cg_device(nullptr); - static_set_gamma(true, 1.0f); + if (_gamma_changed) { + static_set_gamma(true, 1.0f); + } } /** From 1c50abb79b061c1c8a2b493c5ea09975bf31e2ec Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 20:57:21 +0100 Subject: [PATCH 06/23] Add support for Maya 2020 --- makepanda/makepandacore.py | 1 + pandatool/src/mayaprogs/mayapath.cxx | 1 + 2 files changed, 2 insertions(+) diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 9cb726e20a..324d1ee43d 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -106,6 +106,7 @@ MAYAVERSIONINFO = [("MAYA6", "6.0"), ("MAYA2017","2017"), ("MAYA2018","2018"), ("MAYA2019","2019"), + ("MAYA2020","2020"), ] MAXVERSIONINFO = [("MAX6", "SOFTWARE\\Autodesk\\3DSMAX\\6.0", "installdir", "maxsdk\\cssdk\\include"), diff --git a/pandatool/src/mayaprogs/mayapath.cxx b/pandatool/src/mayaprogs/mayapath.cxx index 78198f8e74..d64f4c2ac5 100644 --- a/pandatool/src/mayaprogs/mayapath.cxx +++ b/pandatool/src/mayaprogs/mayapath.cxx @@ -107,6 +107,7 @@ struct MayaVerInfo maya_versions[] = { { "MAYA2017", "2017"}, { "MAYA2018", "2018"}, { "MAYA2019", "2019"}, + { "MAYA2020", "2020"}, { 0, 0 }, }; From 7b5e11e9c99c7d298057719cc6b8c70cc3c3ce3c Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 20:57:44 +0100 Subject: [PATCH 07/23] makepanda: add support for Windows 10.0.18362.0 SDK --- makepanda/makepandacore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 324d1ee43d..01a50199a7 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -2853,7 +2853,7 @@ def SetupVisualStudioEnviron(): elif not win_kit.endswith('\\'): win_kit += '\\' - for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763: + for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763, 18362: version = "10.0.{0}.0".format(vnum) if os.path.isfile(win_kit + "Include\\" + version + "\\ucrt\\assert.h"): print("Using Universal CRT %s" % (version)) From c2a5b08de528269b5ec0ac0c1923197a9c08e456 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 20:58:13 +0100 Subject: [PATCH 08/23] mayapath: fix maya tools when running from pip installation Fixes #709 --- pandatool/src/mayaprogs/mayapath.cxx | 32 ++++++++++++---------------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/pandatool/src/mayaprogs/mayapath.cxx b/pandatool/src/mayaprogs/mayapath.cxx index d64f4c2ac5..1f42d359ee 100644 --- a/pandatool/src/mayaprogs/mayapath.cxx +++ b/pandatool/src/mayaprogs/mayapath.cxx @@ -195,26 +195,22 @@ int main(int argc, char *argv[]) { // First, get the command line and append _bin, so we will actually run // maya2egg_bin.exe, egg2maya_bin.exe, etc. - Filename command = Filename::from_os_specific(argv[0]); - if (!command.is_fully_qualified()) { - DSearchPath path; - path.append_path(ExecutionEnvironment::get_environment_variable("PATH")); -#ifdef _WIN32 - command.set_extension("exe"); -#endif - command.resolve_filename(path); + Filename command = ExecutionEnvironment::get_binary_name(); + + if (command.empty() || command == "unknown" || !command.exists()) { + command = Filename::from_os_specific(argv[0]); + + if (!command.is_fully_qualified()) { + DSearchPath path; + path.append_path(ExecutionEnvironment::get_environment_variable("PATH")); + #ifdef _WIN32 + command.set_extension("exe"); + #endif + command.resolve_filename(path); + } } -#ifdef _WIN32 - if (command.get_extension() == "exe") { - command.set_extension(""); - } -#endif - - command = command.get_fullpath() + string("_bin"); -#ifdef _WIN32 - command.set_extension("exe"); -#endif + command.set_basename_wo_extension(command.get_basename_wo_extension() + "_bin"); string os_command = command.to_os_specific(); // First start with $PANDA_MAYA_LOCATION. If it is set, it overrides From 5eb40b90619060ee62ab43288646d4b4bb243c52 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 21:27:58 +0100 Subject: [PATCH 09/23] makewheel: remove maya2egg#_bin.exe from entry_points.txt These are not intended to be invoked by the user directly, so .exe wrappers do not need to be generated. maya2egg will find the _bin equivalent by looking for it next to the executable itself. --- makepanda/makewheel.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index f8d9b56ef9..1ba176116c 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -688,10 +688,15 @@ __version__ = '{0}' # Put the .exe files inside the panda3d-tools directory. whl.write_file('panda3d_tools/' + file, source_path) + if basename.endswith('_bin'): + # These tools won't be invoked by the user directly. + continue + # Tell pip to create a wrapper script. funcname = basename.replace('-', '_') entry_points += '{0} = panda3d_tools:{1}\n'.format(basename, funcname) tools_init += '{0} = lambda: _exec_tool({1!r})\n'.format(funcname, file) + entry_points += '[distutils.commands]\n' entry_points += 'build_apps = direct.dist.commands:build_apps\n' entry_points += 'bdist_apps = direct.dist.commands:bdist_apps\n' From 2f31c9ce68e17de80583f3f9906e3c421ec3b8bd Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 23:46:58 +0100 Subject: [PATCH 10/23] stdpy: recognize daemon=True argument in Thread constructor --- direct/src/stdpy/threading.py | 7 +++++-- direct/src/stdpy/threading2.py | 9 ++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/direct/src/stdpy/threading.py b/direct/src/stdpy/threading.py index 45409f9e18..555f274ee2 100644 --- a/direct/src/stdpy/threading.py +++ b/direct/src/stdpy/threading.py @@ -87,7 +87,7 @@ class Thread(ThreadBase): object. The wrapper is designed to emulate Python's own threading.Thread object. """ - def __init__(self, group=None, target=None, name=None, args=(), kwargs={}): + def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, daemon=None): ThreadBase.__init__(self) assert group is None @@ -99,7 +99,10 @@ class Thread(ThreadBase): name = _newname() current = current_thread() - self.__dict__['daemon'] = current.daemon + if daemon is not None: + self.__dict__['daemon'] = daemon + else: + self.__dict__['daemon'] = current.daemon self.__dict__['name'] = name def call_run(): diff --git a/direct/src/stdpy/threading2.py b/direct/src/stdpy/threading2.py index 6e25f5208c..f1f2e12b12 100644 --- a/direct/src/stdpy/threading2.py +++ b/direct/src/stdpy/threading2.py @@ -396,7 +396,7 @@ class Thread(_Verbose): __exc_info = _sys.exc_info def __init__(self, group=None, target=None, name=None, - args=(), kwargs=None, verbose=None): + args=(), kwargs=None, verbose=None, daemon=None): assert group is None, "group argument must be None for now" _Verbose.__init__(self, verbose) if kwargs is None: @@ -405,7 +405,10 @@ class Thread(_Verbose): self.__name = str(name or _newname()) self.__args = args self.__kwargs = kwargs - self.__daemonic = self._set_daemon() + if daemon is not None: + self.__daemonic = daemon + else: + self.__daemonic = self._set_daemon() self.__started = False self.__stopped = False self.__block = Condition(Lock()) @@ -670,7 +673,7 @@ class _MainThread(Thread): class _DummyThread(Thread): def __init__(self): - Thread.__init__(self, name=_newname("Dummy-%d")) + Thread.__init__(self, name=_newname("Dummy-%d"), daemon=True) # Thread.__block consumes an OS-level locking primitive, which # can never be used by a _DummyThread. Since a _DummyThread From bb3bfebdc24eb399a1a65f9e74bcb3dfe2b87633 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 23:48:04 +0100 Subject: [PATCH 11/23] stdpy: support name and daemon properties in threading2 module --- direct/src/stdpy/threading2.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/direct/src/stdpy/threading2.py b/direct/src/stdpy/threading2.py index f1f2e12b12..e5c2ab9991 100644 --- a/direct/src/stdpy/threading2.py +++ b/direct/src/stdpy/threading2.py @@ -602,6 +602,9 @@ class Thread(_Verbose): assert not self.__started, "cannot set daemon status of active thread" self.__daemonic = daemonic + name = property(getName, setName) + daemon = property(isDaemon, setDaemon) + # The timer class was contributed by Itamar Shtull-Trauring def Timer(*args, **kwargs): From c0fd600454107a608fe78a7ee899054c312bcf89 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 23:51:24 +0100 Subject: [PATCH 12/23] stdpy: threading2: join non-daemonic threads at interpreter shutdown Fixes #758 --- direct/src/stdpy/threading2.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/direct/src/stdpy/threading2.py b/direct/src/stdpy/threading2.py index e5c2ab9991..6630bb1738 100644 --- a/direct/src/stdpy/threading2.py +++ b/direct/src/stdpy/threading2.py @@ -14,6 +14,7 @@ module, and so it is therefore layered on top of Panda's thread implementation. """ import sys as _sys +import atexit as _atexit from direct.stdpy import thread as _thread from direct.stdpy.thread import stack_size, _newname, _local as local @@ -395,6 +396,10 @@ class Thread(_Verbose): # operation on/with a NoneType __exc_info = _sys.exc_info + # Set to True when the _shutdown handler is registered as atexit function. + # Protected by _active_limbo_lock. + __registered_atexit = False + def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None, daemon=None): assert group is None, "group argument must be None for now" @@ -439,6 +444,14 @@ class Thread(_Verbose): self._note("%s.start(): starting thread", self) _active_limbo_lock.acquire() _limbo[self] = self + + # If we are starting a non-daemon thread, we need to call join() on it + # when the interpreter exits. Python will call _shutdown() on the + # built-in threading module automatically, but not on our module. + if not self.__daemonic and not Thread.__registered_atexit: + _atexit.register(_shutdown) + Thread.__registered_atexit = True + _active_limbo_lock.release() _start_new_thread(self.__bootstrap, ()) self.__started = True From 8c82cf5800ce2be71b9cc4cfe9fec469bfbfb162 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 29 Dec 2019 00:27:59 +0100 Subject: [PATCH 13/23] makepanda: --universal should not enable i386 when targeting 10.15+ [skip ci] --- makepanda/makepanda.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 884b79733a..a67422c6c5 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -306,13 +306,15 @@ def parseopts(args): if target_arch: exit("--universal is incompatible with --arch") - OSX_ARCHS.append("i386") if OSXTARGET: osxver = OSXTARGET else: maj, min = platform.mac_ver()[0].split('.')[:2] osxver = int(maj), int(min) + if osxver[1] < 15: + OSX_ARCHS.append("i386") + if osxver[1] < 6: OSX_ARCHS.append("ppc") else: From 7aab057245c11bb72ef3897fc1cc283cca2d8d7c Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 21:25:41 -0500 Subject: [PATCH 14/23] makepanda: change strange rpath argument for maya2egg on macOS It doesn't seem like this setting is actually needed (because mayapath does the necessary set-up), but while it's set, we might as well set it to something more sensible. --- makepanda/makepanda.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index a67422c6c5..6cecc8cc31 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1083,7 +1083,7 @@ if (COMPILER=="GCC"): for pkg in MAYAVERSIONS: if (PkgSkip(pkg)==0 and (pkg in SDK)): if GetTarget() == 'darwin': - LibName(pkg, "-Wl,-rpath," + SDK[pkg] + "/Maya.app/Contents/MacOS") + LibName(pkg, "-Wl,-rpath,/Applications/Autodesk/" + pkg.lower() + "/Maya.app/Contents/MacOS") else: LibName(pkg, "-Wl,-rpath," + SDK[pkg] + "/lib") LibName(pkg, "-lOpenMaya") From 4c3b6fcc033a9f13e5f8688eaed34a31d17130d7 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 28 Dec 2019 21:27:51 -0500 Subject: [PATCH 15/23] makepanda: libIMFbase.dylib is no longer shipped with Maya 2020 on macOS --- makepanda/makepanda.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 6cecc8cc31..d2ce07cc3c 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1106,7 +1106,8 @@ if (COMPILER=="GCC"): LibName(pkg, "-lDependEngine") LibName(pkg, "-lCommandEngine") LibName(pkg, "-lFoundation") - LibName(pkg, "-lIMFbase") + if pkg != "MAYA2020": + LibName(pkg, "-lIMFbase") if GetTarget() != 'darwin': LibName(pkg, "-lOpenMayalib") else: From 8bb9abfbb0a648fdcccd96800809be62195d9082 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 25 Dec 2019 17:16:02 +0100 Subject: [PATCH 16/23] x11display: fix compile warnings --- panda/src/x11display/x11GraphicsPipe.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/panda/src/x11display/x11GraphicsPipe.cxx b/panda/src/x11display/x11GraphicsPipe.cxx index 6050911fb4..8f87b57609 100644 --- a/panda/src/x11display/x11GraphicsPipe.cxx +++ b/panda/src/x11display/x11GraphicsPipe.cxx @@ -371,13 +371,13 @@ find_fullscreen_crtc(const LPoint2i &point, 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) { + if (point[0] >= info->x && point[0] < info->x + (int)info->width && + point[1] >= info->y && point[1] < info->y + (int)info->height) { x = info->x; y = info->y; - width = info->width; - height = info->height; + width = (int)info->width; + height = (int)info->height; return crtc; } } From 530955b53e26ba416ef26e95fcb66ea5d2fec242 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 29 Dec 2019 14:19:42 +0100 Subject: [PATCH 17/23] makepanda: add explicit link to libOpenMayaUI.dylib on macOS This is needed when compiling without -undefined dynamic_lookup --- makepanda/makepanda.py | 1 + 1 file changed, 1 insertion(+) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index d2ce07cc3c..3232441ddc 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1088,6 +1088,7 @@ if (COMPILER=="GCC"): LibName(pkg, "-Wl,-rpath," + SDK[pkg] + "/lib") LibName(pkg, "-lOpenMaya") LibName(pkg, "-lOpenMayaAnim") + LibName(pkg, "-lOpenMayaUI") LibName(pkg, "-lAnimSlice") LibName(pkg, "-lDeformSlice") LibName(pkg, "-lModifiers") From 0926a3cde529afb1e1753df8e0f666e058b25918 Mon Sep 17 00:00:00 2001 From: MDTech-us-MAN Date: Sun, 29 Dec 2019 14:23:03 +0100 Subject: [PATCH 18/23] readme: update Android build instructions (from #716) --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 623052b7fa..d2c4f3fe4f 100644 --- a/README.md +++ b/README.md @@ -186,16 +186,19 @@ from the Play Store. Many of the dependencies can be installed by running the following command in the Termux shell: ```bash -pkg install python-dev termux-tools ndk-stl ndk-sysroot clang libvorbis-dev libopus-dev opusfile-dev openal-soft-dev freetype-dev harfbuzz-dev libpng-dev ecj4.6 dx patchelf aapt apksigner libcrypt-dev +pkg install python ndk-sysroot clang bison freetype harfbuzz libpng eigen openal-soft opusfile libvorbis assimp libopus ecj dx patchelf aapt apksigner libcrypt openssl pkg-config ``` -Then, you can build and install the .apk right away using these commands: +Then, you can build the .apk using this command: ```bash python makepanda/makepanda.py --everything --target android-21 --no-tiff --installer -xdg-open panda3d.apk ``` +You can install the generated panda3d.apk by browsing to the panda3d folder +using a file manager. You may need to copy it to `/sdcard` to be able to +access it from other apps. + To launch a Python program from Termux, you can use the `run_python.sh` script inside the `panda/src/android` directory. It will launch Python in a separate activity, load it with the Python script you passed as argument, and use a From 0972dfa457005ad3f5a97a758901238cff208d8d Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 29 Dec 2019 14:27:05 +0100 Subject: [PATCH 19/23] dcparser: fix ability to compile outside of Panda Fixes #759 --- direct/src/dcparser/dcPackerInterface.h | 1 - direct/src/dcparser/dcParserDefs.h | 1 - direct/src/dcparser/dcbase.h | 4 ++++ direct/src/dcparser/hashGenerator.h | 1 - 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/direct/src/dcparser/dcPackerInterface.h b/direct/src/dcparser/dcPackerInterface.h index 0b2f81d2fe..1f4ac4a47f 100644 --- a/direct/src/dcparser/dcPackerInterface.h +++ b/direct/src/dcparser/dcPackerInterface.h @@ -16,7 +16,6 @@ #include "dcbase.h" #include "dcSubatomicType.h" -#include "vector_uchar.h" class DCFile; class DCField; diff --git a/direct/src/dcparser/dcParserDefs.h b/direct/src/dcparser/dcParserDefs.h index f6f7aacd71..9c7c589753 100644 --- a/direct/src/dcparser/dcParserDefs.h +++ b/direct/src/dcparser/dcParserDefs.h @@ -16,7 +16,6 @@ #include "dcbase.h" #include "dcSubatomicType.h" -#include "vector_uchar.h" class DCFile; class DCClass; diff --git a/direct/src/dcparser/dcbase.h b/direct/src/dcparser/dcbase.h index 64ef117158..3a3fbbd13e 100644 --- a/direct/src/dcparser/dcbase.h +++ b/direct/src/dcparser/dcbase.h @@ -32,6 +32,7 @@ #include "pvector.h" #include "pmap.h" #include "pset.h" +#include "vector_uchar.h" #else // WITHIN_PANDA @@ -81,6 +82,7 @@ #define nassertr_always(condition, return_value) assert(condition) #define nassertv(condition) assert(condition) #define nassertv_always(condition) assert(condition) +#define nassert_raise(message) {std::cerr << message << std::endl; abort();} // Panda defines a special Filename class. We'll use an ordinary string // instead. @@ -97,8 +99,10 @@ typedef std::string Filename; #define pvector std::vector #define pmap std::map #define pset std::set +#define vector_uchar std::vector #include +#include typedef std::ifstream pifstream; typedef std::ofstream pofstream; diff --git a/direct/src/dcparser/hashGenerator.h b/direct/src/dcparser/hashGenerator.h index 472e858cb0..7779dda735 100644 --- a/direct/src/dcparser/hashGenerator.h +++ b/direct/src/dcparser/hashGenerator.h @@ -16,7 +16,6 @@ #include "dcbase.h" #include "primeNumberGenerator.h" -#include "vector_uchar.h" /** * This class generates an arbitrary hash number from a sequence of ints. From 15d6e0c5430a038c50a6bd7d9a63adfda69cd99d Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 29 Dec 2019 14:57:43 +0100 Subject: [PATCH 20/23] actor: support custom Python loader hooks Fixes #750 --- direct/src/actor/Actor.py | 4 ++++ direct/src/showbase/Loader.py | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/direct/src/actor/Actor.py b/direct/src/actor/Actor.py index f99a18bbdf..11d4990351 100644 --- a/direct/src/actor/Actor.py +++ b/direct/src/actor/Actor.py @@ -5,6 +5,7 @@ __all__ = ['Actor'] from panda3d.core import * from panda3d.core import Loader as PandaLoader from direct.showbase.DirectObject import DirectObject +from direct.showbase.Loader import Loader from direct.directnotify import DirectNotifyGlobal @@ -1886,6 +1887,9 @@ class Actor(DirectObject, NodePath): else: loaderOptions.setFlags(loaderOptions.getFlags() | LoaderOptions.LFReportErrors) + # Ensure that custom Python loader hooks are initialized. + Loader._loadPythonFileTypes() + # Pass loaderOptions to specify that we want to # get the skeleton model. This only matters to model # files (like .mb) for which we can choose to extract diff --git a/direct/src/showbase/Loader.py b/direct/src/showbase/Loader.py index f0afbc06ec..80aa5f09e2 100644 --- a/direct/src/showbase/Loader.py +++ b/direct/src/showbase/Loader.py @@ -22,6 +22,8 @@ class Loader(DirectObject): notify = directNotify.newCategory("Loader") loaderIndex = 0 + _loadedPythonFileTypes = False + class Callback: """Returned by loadModel when used asynchronously. This class is modelled after Future, and can be awaited.""" @@ -149,8 +151,7 @@ class Loader(DirectObject): Loader.loaderIndex += 1 self.accept(self.hook, self.__gotAsyncObject) - if ConfigVariableBool('loader-support-entry-points', True): - self._loadPythonFileTypes() + self._loadPythonFileTypes() def destroy(self): self.ignore(self.hook) @@ -158,7 +159,14 @@ class Loader(DirectObject): del self.base del self.loader - def _loadPythonFileTypes(self): + @classmethod + def _loadPythonFileTypes(cls): + if cls._loadedPythonFileTypes: + return + + if not ConfigVariableBool('loader-support-entry-points', True): + return + import importlib try: pkg_resources = importlib.import_module('pkg_resources') @@ -171,6 +179,8 @@ class Loader(DirectObject): for entry_point in pkg_resources.iter_entry_points('panda3d.loaders'): registry.register_deferred_type(entry_point) + cls._loadedPythonFileTypes = True + # model loading funcs def loadModel(self, modelPath, loaderOptions = None, noCache = None, allowInstance = False, okMissing = None, From 2d11f36c9eca48227e4bf37db08236daae76ebcf Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 29 Dec 2019 15:06:24 +0100 Subject: [PATCH 21/23] makepanda: add docstring for panda3d.dtoolconfig module --- makepanda/makepanda.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 3232441ddc..237535771b 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2949,7 +2949,13 @@ if not PkgSkip("PYTHON"): ConditionalWriteFile(GetOutputDir() + '/panda3d/__init__.py', p3d_init) # Also add this file, for backward compatibility. - ConditionalWriteFile(GetOutputDir() + '/panda3d/dtoolconfig.py', """ + ConditionalWriteFile(GetOutputDir() + '/panda3d/dtoolconfig.py', """\ +'''Alias of :mod:`panda3d.interrogatedb`. + +.. deprecated:: 1.10.0 + This module has been renamed to :mod:`panda3d.interrogatedb`. +''' + if __debug__: print("Warning: panda3d.dtoolconfig is deprecated, use panda3d.interrogatedb instead.") from .interrogatedb import * From fccffb4932fd6c0808673b999064ddd51ca9b509 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 29 Dec 2019 17:47:36 +0100 Subject: [PATCH 22/23] glgsg: fix texture extraction of MRTs in OpenGL ES Fixes #815 --- .../glstuff/glGraphicsStateGuardian_src.cxx | 25 ++++++++++++++++--- .../src/glstuff/glGraphicsStateGuardian_src.h | 5 ++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index b510d9d4b9..094df8ece4 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2523,6 +2523,20 @@ reset() { } #endif +#if defined(OPENGLES) && !defined(OPENGLES_1) + if (is_at_least_gles_version(3, 0)) { + _glReadBuffer = (PFNGLREADBUFFERPROC) + get_extension_func("glReadBuffer"); + + } else if (has_extension("GL_NV_read_buffer")) { + _glReadBuffer = (PFNGLREADBUFFERPROC) + get_extension_func("glReadBufferNV"); + + } else { + _glReadBuffer = nullptr; + } +#endif + #ifndef OPENGLES_1 _max_color_targets = 1; if (_glDrawBuffers != nullptr) { @@ -8868,7 +8882,7 @@ set_draw_buffer(int rbtype) { */ void CLP(GraphicsStateGuardian):: set_read_buffer(int rbtype) { -#ifndef OPENGLES // Draw buffers not supported by OpenGL ES. (TODO!) +#ifndef OPENGLES_1 // Draw buffers not supported by OpenGL ES 1. if (rbtype & (RenderBuffer::T_depth | RenderBuffer::T_stencil)) { // Special case: don't have to call ReadBuffer for these. return; @@ -8901,10 +8915,14 @@ set_read_buffer(int rbtype) { } ++index; } +#ifdef OPENGLES + _glReadBuffer(buffer); +#else glReadBuffer(buffer); +#endif } else { - +#ifndef OPENGLES switch (rbtype & RenderBuffer::T_color) { case RenderBuffer::T_front: glReadBuffer(GL_FRONT); @@ -8941,10 +8959,11 @@ set_read_buffer(int rbtype) { default: break; } +#endif // OPENGLES } report_my_gl_errors(); -#endif // OPENGLES +#endif // OPENGLES_1 } /** diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 3fd89c8ad1..1b5a1cdfb4 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -92,6 +92,7 @@ typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (APIENTRYP PFNGLREADBUFFERPROC) (GLenum src); typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); @@ -935,6 +936,10 @@ public: PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer; PFNGLDRAWBUFFERSPROC _glDrawBuffers; +#if defined(OPENGLES) && !defined(OPENGLES_1) + PFNGLREADBUFFERPROC _glReadBuffer; +#endif + #ifndef OPENGLES_1 PFNGLCLEARBUFFERFVPROC _glClearBufferfv; PFNGLCLEARBUFFERIVPROC _glClearBufferiv; From 45461e667a84b793048db0092596b5c23dbe6b38 Mon Sep 17 00:00:00 2001 From: LD Date: Sat, 14 Dec 2019 18:07:28 +0100 Subject: [PATCH 23/23] cocoadisplay: use same scaling factor as the current view when switching to fullscreen on MacOS 10.15+ Fixes #794 --- panda/src/cocoadisplay/cocoaGraphicsWindow.mm | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm index 5f7dfde474..a14f099d3e 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsWindow.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsWindow.mm @@ -45,6 +45,10 @@ TypeHandle CocoaGraphicsWindow::_type_handle; +#ifndef MAC_OS_X_VERSION_10_15 +#define NSAppKitVersionNumber10_14 1671 +#endif + /** * */ @@ -1107,7 +1111,28 @@ set_properties_now(WindowProperties &properties) { #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 CGDisplayModeRef CocoaGraphicsWindow:: find_display_mode(int width, int height) { - CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, NULL); + CFDictionaryRef options = NULL; + // On macOS 10.15+ (Catalina), we want to select the display mode with the + // samescaling factor as the current view to avoid cropping or scaling issues. + // This is a workaround until HiDPI display or scaling factor is properly + // handled. CGDisplayCopyAllDisplayModes() does not return upscaled display + // mode unless explicitly asked with kCGDisplayShowDuplicateLowResolutionModes + // (which is undocumented...). +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_14) { + const CFStringRef dictkeys[] = {kCGDisplayShowDuplicateLowResolutionModes}; + const CFBooleanRef dictvalues[] = {kCFBooleanTrue}; + options = CFDictionaryCreate(NULL, + (const void **)dictkeys, + (const void **)dictvalues, + 1, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } +#endif + CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, options); + CFRelease(options); + size_t num_modes = CFArrayGetCount(modes); CGDisplayModeRef mode; @@ -1116,14 +1141,22 @@ find_display_mode(int width, int height) { int refresh_rate; mode = CGDisplayCopyDisplayMode(_display); +#if __MAC_OS_X_VERSION_MAX_ALLOWED < 1080 // First check if the current mode is adequate. if (CGDisplayModeGetWidth(mode) == width && CGDisplayModeGetHeight(mode) == height) { return mode; } +#endif current_pixel_encoding = CGDisplayModeCopyPixelEncoding(mode); refresh_rate = CGDisplayModeGetRefreshRate(mode); +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + // Calculate the pixel width and height of the fullscreen mode we want using + // the currentdisplay mode dimensions and pixel dimensions. + size_t expected_pixel_width = (size_t(width) * CGDisplayModeGetPixelWidth(mode)) / CGDisplayModeGetWidth(mode); + size_t expected_pixel_height = (size_t(height) * CGDisplayModeGetPixelHeight(mode)) / CGDisplayModeGetHeight(mode); +#endif CGDisplayModeRelease(mode); for (size_t i = 0; i < num_modes; ++i) { @@ -1131,9 +1164,17 @@ find_display_mode(int width, int height) { CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(mode); + // As explained above, we want to select the fullscreen display mode using + // the same scaling factor, but only for MacOS 10.15+ To do this we check + // the mode width and heightbut also actual pixel widh and height. if (CGDisplayModeGetWidth(mode) == width && CGDisplayModeGetHeight(mode) == height && CGDisplayModeGetRefreshRate(mode) == refresh_rate && +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 + (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_14 || + (CGDisplayModeGetPixelWidth(mode) == expected_pixel_width && + CGDisplayModeGetPixelHeight(mode) == expected_pixel_height)) && +#endif CFStringCompare(pixel_encoding, current_pixel_encoding, 0) == kCFCompareEqualTo) { CFRetain(mode);