From 4a8f1839eafeaf107ea3b3f59c35137116e69712 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 1 Dec 2016 17:36:38 +0100 Subject: [PATCH 01/70] 1.9: change to support .whl distribution (putting panda DLLs in panda3d/ dir) --- .../extensions_native/extension_native_helpers.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/direct/src/extensions_native/extension_native_helpers.py b/direct/src/extensions_native/extension_native_helpers.py index 20afc7ddef..e17457b872 100644 --- a/direct/src/extensions_native/extension_native_helpers.py +++ b/direct/src/extensions_native/extension_native_helpers.py @@ -50,9 +50,18 @@ if sys.platform == "win32": filename = "libpandaexpress%s%s" % (dll_suffix, dll_ext) for dir in sys.path + [sys.prefix]: lib = os.path.join(dir, filename) - if (os.path.exists(lib)): + if os.path.exists(lib): target = dir - if target == None: + + # Perhaps it is in the same directory as panda3d/core.pyd ? + if target is None: + for dir in sys.path: + lib = os.path.join(dir, 'panda3d', filename) + if os.path.exists(lib): + target = os.path.join(dir, 'panda3d') + break + + if target is None: message = "Cannot find %s" % (filename) raise ImportError(message) From 2b6e192e5aeb9c1b5078815c15735698f4ed1b6b Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 3 Dec 2016 01:04:35 +0100 Subject: [PATCH 02/70] Protect against overallocation when reading corrupt texture from bam --- panda/src/gobj/texture.cxx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index fa16fa7ab8..bcabaa7a8c 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -8271,6 +8271,14 @@ do_fillin_body(CData *cdata, DatagramIterator &scan, BamReader *manager) { cdata->_simple_image_date_generated = scan.get_int32(); size_t u_size = scan.get_uint32(); + + // Protect against large allocation. + if (u_size > scan.get_remaining_size()) { + gobj_cat.error() + << "simple RAM image extends past end of datagram, is texture corrupt?\n"; + return; + } + PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type()); scan.extract_bytes(image.p(), u_size); @@ -8327,6 +8335,14 @@ do_fillin_rawdata(CData *cdata, DatagramIterator &scan, BamReader *manager) { // fill the cdata->_image buffer with image data size_t u_size = scan.get_uint32(); + + // Protect against large allocation. + if (u_size > scan.get_remaining_size()) { + gobj_cat.error() + << "RAM image " << n << " extends past end of datagram, is texture corrupt?\n"; + return; + } + PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type()); scan.extract_bytes(image.p(), u_size); From 84789ecdd18a3aadd3d6a8cb0ed17bd1acaea531 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 4 Dec 2016 21:28:52 +0100 Subject: [PATCH 03/70] Fix GL compile error on Mac OS X --- panda/src/glstuff/glGraphicsStateGuardian_src.h | 1 + 1 file changed, 1 insertion(+) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 8080670fc5..fe8cff8b59 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -247,6 +247,7 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VPROC) (GLuint index, const GLuin typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VPROC) (GLuint index, GLenum pname, GLuint64EXT *params); typedef void *(APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access); typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data); #endif // OPENGLES #endif // __EDG__ From a056543d5a3863d930535b0f9ad27600f73c5cd6 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 5 Dec 2016 02:02:25 +0100 Subject: [PATCH 04/70] Support push_macro and pop_macro in cppparser --- dtool/src/cppparser/cppPreprocessor.cxx | 33 ++++++++++++++++++++++++- dtool/src/cppparser/cppPreprocessor.h | 3 +++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 5df779fc1d..83050d3c41 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -1461,7 +1461,6 @@ handle_define_directive(const string &args, const YYLTYPE &loc) { CPPManifest *other = result.first->second; warning("redefinition of macro '" + manifest->_name + "'", loc); warning("previous definition is here", other->_loc); - delete other; result.first->second = manifest; } } @@ -1679,6 +1678,38 @@ handle_pragma_directive(const string &args, const YYLTYPE &loc) { assert(it != _parsed_files.end()); it->_pragma_once = true; } + + char macro[64]; + if (sscanf(args.c_str(), "push_macro ( \"%63[^\"]\" )", macro) == 1) { + // We just mark it as pushed for now, so that the next time someone tries + // to override it, we save the old value. + Manifests::iterator mi = _manifests.find(macro); + if (mi != _manifests.end()) { + _manifest_stack[macro].push_back(mi->second); + } else { + _manifest_stack[macro].push_back(NULL); + } + + } else if (sscanf(args.c_str(), "pop_macro ( \"%63[^\"]\" )", macro) == 1) { + ManifestStack &stack = _manifest_stack[macro]; + if (stack.size() > 0) { + CPPManifest *manifest = stack.back(); + stack.pop_back(); + Manifests::iterator mi = _manifests.find(macro); + if (manifest == NULL) { + // It was undefined when it was pushed, so make it undefined again. + if (mi != _manifests.end()) { + _manifests.erase(mi); + } + } else if (mi != _manifests.end()) { + mi->second = manifest; + } else { + _manifests.insert(Manifests::value_type(macro, manifest)); + } + } else { + warning("pop_macro without matching push_macro", loc); + } + } } /** diff --git a/dtool/src/cppparser/cppPreprocessor.h b/dtool/src/cppparser/cppPreprocessor.h index 74ff8edcf1..e375b259dd 100644 --- a/dtool/src/cppparser/cppPreprocessor.h +++ b/dtool/src/cppparser/cppPreprocessor.h @@ -72,6 +72,9 @@ public: typedef map Manifests; Manifests _manifests; + typedef pvector ManifestStack; + map _manifest_stack; + pvector _quote_include_kind; DSearchPath _quote_include_path; DSearchPath _angle_include_path; From 46c8990f40dd0d9e0fddb5a8c1e92acf4b7e0cae Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 5 Dec 2016 12:55:13 -0500 Subject: [PATCH 05/70] Switch to clang by default on Mac; drop burden of supporting GCC 4.2 Also get rid of that annoying message about -pthread in clang. --- makepanda/makepanda.py | 9 ++++----- makepanda/makepandacore.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index bade6c8288..6d0bd9638c 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1686,11 +1686,7 @@ def CompileLink(dll, obj, opts): if 'NOARCH:' + arch.upper() not in opts: cmd += " -arch %s" % arch - if "SYSROOT" in SDK: - cmd += " --sysroot=%s -no-canonical-prefixes" % (SDK["SYSROOT"]) - - # Android-specific flags. - if GetTarget() == 'android': + elif GetTarget() == 'android': cmd += " -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now" if GetTargetArch() == 'armv7a': cmd += " -march=armv7-a -Wl,--fix-cortex-a8" @@ -1698,6 +1694,9 @@ def CompileLink(dll, obj, opts): else: cmd += " -pthread" + if "SYSROOT" in SDK: + cmd += " --sysroot=%s -no-canonical-prefixes" % (SDK["SYSROOT"]) + if LDFLAGS != "": cmd += " " + LDFLAGS diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 2b9e9d4a32..b9899f6adb 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -396,10 +396,16 @@ def CrossCompiling(): return GetTarget() != GetHost() def GetCC(): - return os.environ.get('CC', TOOLCHAIN_PREFIX + 'gcc') + if TARGET == 'darwin': + return os.environ.get('CC', TOOLCHAIN_PREFIX + 'clang') + else: + return os.environ.get('CC', TOOLCHAIN_PREFIX + 'gcc') def GetCXX(): - return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'g++') + if TARGET == 'darwin': + return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'clang++') + else: + return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'g++') def GetStrip(): # Hack From 83507e413fa34d0edc4af6c4c1aa0d7b6f60220d Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 5 Dec 2016 16:30:44 -0500 Subject: [PATCH 06/70] Fix Mac OS X Snow Leopard build --- direct/src/showbase/PythonUtil.py | 37 ++++++++++++++++++++++++++++++- makepanda/makepanda.py | 2 +- makepanda/makepandacore.py | 5 +++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/direct/src/showbase/PythonUtil.py b/direct/src/showbase/PythonUtil.py index ebf8bce63f..0c850f51a0 100644 --- a/direct/src/showbase/PythonUtil.py +++ b/direct/src/showbase/PythonUtil.py @@ -38,7 +38,6 @@ import os import sys import random import time -import importlib __report_indent = 3 @@ -61,6 +60,42 @@ def Functor(function, *args, **kArgs): return functor """ +try: + import importlib +except ImportError: + # Backward compatibility for Python 2.6. + def _resolve_name(name, package, level): + if not hasattr(package, 'rindex'): + raise ValueError("'package' not set to a string") + dot = len(package) + for x in xrange(level, 1, -1): + try: + dot = package.rindex('.', 0, dot) + except ValueError: + raise ValueError("attempted relative import beyond top-level " + "package") + return "%s.%s" % (package[:dot], name) + + def import_module(name, package=None): + if name.startswith('.'): + if not package: + raise TypeError("relative imports require the 'package' argument") + level = 0 + for character in name: + if character != '.': + break + level += 1 + name = _resolve_name(name[level:], package, level) + __import__(name) + return sys.modules[name] + + imp = import_module('imp') + importlib = imp.new_module("importlib") + importlib._resolve_name = _resolve_name + importlib.import_module = import_module + sys.modules['importlib'] = importlib + + class Functor: def __init__(self, function, *args, **kargs): assert callable(function), "function should be a callable obj" diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 6d0bd9638c..990c32f5e5 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -4599,7 +4599,7 @@ if (GetTarget() == 'darwin' and PkgSkip("COCOA")==0 and PkgSkip("GL")==0 and not if (PkgSkip('PANDAFX')==0): TargetAdd('libpandagl.dll', input='libpandafx.dll') TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'COCOA']) + TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'COCOA', 'CARBON']) # # DIRECTORY: panda/src/osxdisplay/ diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index b9899f6adb..2eb4342b06 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -2002,6 +2002,11 @@ def SdkLocatePython(prefer_thirdparty_python=False): SDK["PYTHONVERSION"] = "python" + ver SDK["PYTHONEXEC"] = "/System/Library/Frameworks/Python.framework/Versions/" + ver + "/bin/python" + ver + # Avoid choosing the one in the thirdparty package dir. + PkgSetCustomLocation("PYTHON") + IncDirectory("PYTHON", py_fwx + "/include") + LibDirectory("PYTHON", "%s/usr/lib" % (SDK.get("MACOSX", ""))) + if sys.version[:3] != ver: print("Warning: building with Python %s instead of %s since you targeted a specific Mac OS X version." % (ver, sys.version[:3])) From c410d812ffed47dea8379db2340a8af7eaac9d6c Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 5 Dec 2016 16:31:44 -0500 Subject: [PATCH 07/70] Remove some settings from dtool_config.h to prevent rebuilds: - HAVE_OPENCV - OPENCV_VER_23 - HAVE_FFMPEG - HAVE_SWSCALE - HAVE_SWRESAMPLE --- makepanda/makepanda.py | 30 ++++++++++++++++++-------- panda/src/ffmpeg/ffmpegAudioCursor.cxx | 2 -- panda/src/ffmpeg/ffmpegAudioCursor.h | 5 ----- panda/src/vision/openCVTexture.cxx | 16 ++++++++++++++ panda/src/vision/openCVTexture.h | 16 +------------- 5 files changed, 38 insertions(+), 31 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 990c32f5e5..2c26091ef4 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2236,11 +2236,7 @@ DTOOL_CONFIG=[ ("HAVE_CG", 'UNDEF', 'UNDEF'), ("HAVE_CGGL", 'UNDEF', 'UNDEF'), ("HAVE_CGDX9", 'UNDEF', 'UNDEF'), - ("HAVE_FFMPEG", 'UNDEF', 'UNDEF'), - ("HAVE_SWSCALE", 'UNDEF', 'UNDEF'), - ("HAVE_SWRESAMPLE", 'UNDEF', 'UNDEF'), ("HAVE_ARTOOLKIT", 'UNDEF', 'UNDEF'), - ("HAVE_OPENCV", 'UNDEF', 'UNDEF'), ("HAVE_DIRECTCAM", 'UNDEF', 'UNDEF'), ("HAVE_SQUISH", 'UNDEF', 'UNDEF'), ("HAVE_CARBON", 'UNDEF', 'UNDEF'), @@ -2295,9 +2291,6 @@ def WriteConfigSettings(): else: dtool_config["HAVE_"+x] = 'UNDEF' - if not PkgSkip("OPENCV"): - dtool_config["OPENCV_VER_23"] = '1' if OPENCV_VER_23 else 'UNDEF' - dtool_config["HAVE_NET"] = '1' if (PkgSkip("NVIDIACG")==0): @@ -4128,8 +4121,20 @@ if (not RUNTIME): # if (PkgSkip("VISION") == 0) and (not RUNTIME): + # We want to know whether we have ffmpeg so that we can override the .avi association. + if not PkgSkip("FFMPEG"): + DefSymbol("OPENCV", "HAVE_FFMPEG") + if not PkgSkip("OPENCV"): + DefSymbol("OPENCV", "HAVE_OPENCV") + if OPENCV_VER_23: + DefSymbol("OPENCV", "OPENCV_VER_23") + OPTS=['DIR:panda/src/vision', 'BUILDING:VISION', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG', 'EXCEPTIONS'] - TargetAdd('p3vision_composite1.obj', opts=OPTS, input='p3vision_composite1.cxx') + TargetAdd('p3vision_composite1.obj', opts=OPTS, input='p3vision_composite1.cxx', dep=[ + 'dtool_have_ffmpeg.dat', + 'dtool_have_opencv.dat', + 'dtool_have_directcam.dat', + ]) TargetAdd('libp3vision.dll', input='p3vision_composite1.obj') TargetAdd('libp3vision.dll', input=COMMON_PANDA_LIBS) @@ -4318,8 +4323,15 @@ if (PkgSkip("VRPN")==0 and not RUNTIME): # DIRECTORY: panda/src/ffmpeg # if PkgSkip("FFMPEG") == 0 and not RUNTIME: + if not PkgSkip("SWSCALE"): + DefSymbol("FFMPEG", "HAVE_SWSCALE") + if not PkgSkip("SWRESAMPLE"): + DefSymbol("FFMPEG", "HAVE_SWRESAMPLE") + OPTS=['DIR:panda/src/ffmpeg', 'BUILDING:FFMPEG', 'FFMPEG', 'SWSCALE', 'SWRESAMPLE'] - TargetAdd('p3ffmpeg_composite1.obj', opts=OPTS, input='p3ffmpeg_composite1.cxx') + TargetAdd('p3ffmpeg_composite1.obj', opts=OPTS, input='p3ffmpeg_composite1.cxx', dep=[ + 'dtool_have_swscale.dat', 'dtool_have_swresample.dat']) + TargetAdd('libp3ffmpeg.dll', input='p3ffmpeg_composite1.obj') TargetAdd('libp3ffmpeg.dll', input=COMMON_PANDA_LIBS) TargetAdd('libp3ffmpeg.dll', opts=OPTS) diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.cxx b/panda/src/ffmpeg/ffmpegAudioCursor.cxx index 2f73cff60c..659925cce3 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.cxx +++ b/panda/src/ffmpeg/ffmpegAudioCursor.cxx @@ -50,9 +50,7 @@ FfmpegAudioCursor(FfmpegAudio *src) : _packet_data(0), _format_ctx(0), _audio_ctx(0), -#ifdef HAVE_SWRESAMPLE _resample_ctx(0), -#endif _buffer(0), _buffer_alloc(0), _frame(0) diff --git a/panda/src/ffmpeg/ffmpegAudioCursor.h b/panda/src/ffmpeg/ffmpegAudioCursor.h index 21f79dc62d..ff37fa8bc6 100644 --- a/panda/src/ffmpeg/ffmpegAudioCursor.h +++ b/panda/src/ffmpeg/ffmpegAudioCursor.h @@ -31,10 +31,7 @@ struct AVFormatContext; struct AVCodecContext; struct AVStream; struct AVPacket; - -#ifdef HAVE_SWRESAMPLE struct SwrContext; -#endif /** * A stream that generates a sequence of audio samples. @@ -72,9 +69,7 @@ protected: int _buffer_head; int _buffer_tail; -#ifdef HAVE_SWRESAMPLE SwrContext *_resample_ctx; -#endif public: static TypeHandle get_class_type() { diff --git a/panda/src/vision/openCVTexture.cxx b/panda/src/vision/openCVTexture.cxx index 34c70284b1..7d09636b0c 100644 --- a/panda/src/vision/openCVTexture.cxx +++ b/panda/src/vision/openCVTexture.cxx @@ -21,6 +21,22 @@ #include "bamReader.h" #include "bamCacheRecord.h" +// This symbol is predefined by the Panda3D build system to select whether we +// are using the OpenCV 2.3 or later interface, or if it is not defined, we +// are using the original interface. +#ifdef OPENCV_VER_23 + +#include +// #include +#include + +#else +#include +#include +#include + +#endif // OPENCV_VER_23 + TypeHandle OpenCVTexture::_type_handle; /** diff --git a/panda/src/vision/openCVTexture.h b/panda/src/vision/openCVTexture.h index ad898e51a8..1ad8e11a7a 100644 --- a/panda/src/vision/openCVTexture.h +++ b/panda/src/vision/openCVTexture.h @@ -19,21 +19,7 @@ #include "videoTexture.h" -// This symbol is predefined by the Panda3D build system to select whether we -// are using the OpenCV 2.3 or later interface, or if it is not defined, we -// are using the original interface. -#ifdef OPENCV_VER_23 - -#include -// #include -#include - -#else -#include -#include -#include - -#endif // OPENCV_VER_23 +struct CvCapture; /** * A specialization on VideoTexture that takes its input using the CV library, From 6344c05b18b8f7f32d01e79cab2bd96914a6fd3d Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 5 Dec 2016 17:21:09 -0500 Subject: [PATCH 08/70] Clean up dynamic loading of Win32 funcs, remove makepanda touchinput setting, remove checks for pre-WinXP --- makepanda/makepanda.py | 40 +---- panda/src/dxgsg9/wdxGraphicsPipe9.cxx | 20 ++- panda/src/windisplay/winGraphicsPipe.cxx | 76 ++-------- panda/src/windisplay/winGraphicsPipe.h | 11 -- panda/src/windisplay/winGraphicsWindow.cxx | 162 ++++++++++----------- panda/src/windisplay/winGraphicsWindow.h | 23 ++- 6 files changed, 132 insertions(+), 200 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 2c26091ef4..956e8db52c 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -94,7 +94,6 @@ PkgListSet(["PYTHON", "DIRECT", # Python support "PANDAPARTICLESYSTEM", # Built in particle system "CONTRIB", # Experimental "SSE2", "NEON", # Compiler features - "TOUCHINPUT", # Touchinput interface (requires Windows 7) ]) CheckPandaSourceTree() @@ -170,7 +169,8 @@ def parseopts(args): "version=","lzma","no-python","threads=","outputdir=","override=", "static","host=","debversion=","rpmrelease=","p3dsuffix=","rtdist-version=", "directx-sdk=", "windows-sdk=", "msvc-version=", "clean", "use-icl", - "universal", "target=", "arch=", "git-commit="] + "universal", "target=", "arch=", "git-commit=", + "use-touchinput", "no-touchinput"] anything = 0 optimize = "" target = None @@ -316,18 +316,6 @@ def parseopts(args): print("No Windows SDK version specified. Defaulting to '7.1'.") WINDOWS_SDK = '7.1' - is_win7 = False - if sys.platform == 'win32': - # Note: not available in cygwin. - winver = sys.getwindowsversion() - if winver[0] >= 6 and winver[1] >= 1: - is_win7 = True - - if RUNTIME or not is_win7: - PkgDisable("TOUCHINPUT") - else: - PkgDisable("TOUCHINPUT") - if clean_build and os.path.isdir(GetOutputDir()): print("Deleting %s" % (GetOutputDir())) shutil.rmtree(GetOutputDir()) @@ -1055,14 +1043,11 @@ def CompileCxx(obj,src,opts): cmd += "/favor:blend " cmd += "/wd4996 /wd4275 /wd4273 " - # Enable Windows 7 interfaces if we need Touchinput. - if PkgSkip("TOUCHINPUT") == 0: - cmd += "/DWINVER=0x601 " - else: - cmd += "/DWINVER=0x501 " - # Work around a WinXP/2003 bug when using VS 2015+. - if SDK.get("VISUALSTUDIO_VERSION") == '14.0': - cmd += "/Zc:threadSafeInit- " + # We still target Windows XP. + cmd += "/DWINVER=0x501 " + # Work around a WinXP/2003 bug when using VS 2015+. + if SDK.get("VISUALSTUDIO_VERSION") == '14.0': + cmd += "/Zc:threadSafeInit- " cmd += "/Fo" + obj + " /nologo /c" if GetTargetArch() != 'x64' and (not PkgSkip("SSE2") or 'SSE2' in opts): @@ -1113,12 +1098,7 @@ def CompileCxx(obj,src,opts): if GetTargetArch() == 'x64': cmd += "/favor:blend " cmd += "/wd4996 /wd4275 /wd4267 /wd4101 /wd4273 " - - # Enable Windows 7 interfaces if we need Touchinput. - if PkgSkip("TOUCHINPUT") == 0: - cmd += "/DWINVER=0x601 " - else: - cmd += "/DWINVER=0x501 " + cmd += "/DWINVER=0x501 " cmd += "/Fo" + obj + " /c" for x in ipath: cmd += " /I" + x for (opt,dir) in INCDIRECTORIES: @@ -2129,7 +2109,6 @@ DTOOL_CONFIG=[ ("REPORT_OPENSSL_ERRORS", '1', '1'), ("USE_PANDAFILESTREAM", '1', '1'), ("USE_DELETED_CHAIN", '1', '1'), - ("HAVE_WIN_TOUCHINPUT", 'UNDEF', 'UNDEF'), ("HAVE_GLX", 'UNDEF', '1'), ("HAVE_WGL", '1', 'UNDEF'), ("HAVE_DX9", 'UNDEF', 'UNDEF'), @@ -2347,9 +2326,6 @@ def WriteConfigSettings(): if (PkgSkip("PYTHON") != 0): dtool_config["HAVE_ROCKET_PYTHON"] = 'UNDEF' - if (PkgSkip("TOUCHINPUT") == 0 and GetTarget() == "windows"): - dtool_config["HAVE_WIN_TOUCHINPUT"] = '1' - if (GetOptimize() <= 3): dtool_config["HAVE_ROCKET_DEBUGGER"] = '1' diff --git a/panda/src/dxgsg9/wdxGraphicsPipe9.cxx b/panda/src/dxgsg9/wdxGraphicsPipe9.cxx index 8174105f39..c3c0ee0099 100644 --- a/panda/src/dxgsg9/wdxGraphicsPipe9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsPipe9.cxx @@ -19,6 +19,16 @@ TypeHandle wdxGraphicsPipe9::_type_handle; +static bool MyGetProcAddr(HINSTANCE hDLL, FARPROC *pFn, const char *szExportedFnName) { + *pFn = (FARPROC) GetProcAddress(hDLL, szExportedFnName); + if (*pFn == NULL) { + wdxdisplay9_cat.error() + << "GetProcAddr failed for " << szExportedFnName << ", error=" << GetLastError() < 1MB, card is lying and I cant tell what it is #define UNKNOWN_VIDMEM_SIZE 0xFFFFFFFF @@ -154,7 +164,10 @@ make_output(const string &name, */ bool wdxGraphicsPipe9:: init() { - if (!MyLoadLib(_hDDrawDLL, "ddraw.dll")) { + _hDDrawDLL = LoadLibrary("ddraw.dll"); + if (_hDDrawDLL == NULL) { + wdxdisplay9_cat.error() + << "LoadLibrary failed for ddraw.dll, error=" << GetLastError() <_physical_memory = memory_status.ullTotalPhys; - display_information->_available_physical_memory = memory_status.ullAvailPhys; - display_information->_page_file_size = memory_status.ullTotalPageFile; - display_information->_available_page_file_size = memory_status.ullAvailPageFile; - display_information->_process_virtual_memory = memory_status.ullTotalVirtual; - display_information->_available_process_virtual_memory = memory_status.ullAvailVirtual; - display_information->_memory_load = memory_status.dwMemoryLoad; - } - } else { - MEMORYSTATUS memory_status; - - memory_status.dwLength = sizeof(MEMORYSTATUS); - GlobalMemoryStatus (&memory_status); - - display_information->_physical_memory = memory_status.dwTotalPhys; - display_information->_available_physical_memory = memory_status.dwAvailPhys; - display_information->_page_file_size = memory_status.dwTotalPageFile; - display_information->_available_page_file_size = memory_status.dwAvailPageFile; - display_information->_process_virtual_memory = memory_status.dwTotalVirtual; - display_information->_available_process_virtual_memory = memory_status.dwAvailVirtual; + memory_status.dwLength = sizeof(MEMORYSTATUSEX); + if (GlobalMemoryStatusEx(&memory_status)) { + display_information->_physical_memory = memory_status.ullTotalPhys; + display_information->_available_physical_memory = memory_status.ullAvailPhys; + display_information->_page_file_size = memory_status.ullTotalPageFile; + display_information->_available_page_file_size = memory_status.ullAvailPageFile; + display_information->_process_virtual_memory = memory_status.ullTotalVirtual; + display_information->_available_process_virtual_memory = memory_status.ullAvailVirtual; display_information->_memory_load = memory_status.dwMemoryLoad; } @@ -687,19 +664,12 @@ WinGraphicsPipe() { _supported_types = OT_window | OT_fullscreen_window; - // these fns arent defined on win95, so get dynamic ptrs to them to avoid - // ugly DLL loader failures on w95 - _pfnTrackMouseEvent = NULL; - - _hUser32 = (HINSTANCE)LoadLibrary("user32.dll"); - if (_hUser32 != NULL) { - _pfnTrackMouseEvent = - (PFN_TRACKMOUSEEVENT)GetProcAddress(_hUser32, "TrackMouseEvent"); - + HMODULE user32 = GetModuleHandleA("user32.dll"); + if (user32 != NULL) { if (dpi_aware) { typedef HRESULT (WINAPI *PFN_SETPROCESSDPIAWARENESS)(Process_DPI_Awareness); PFN_SETPROCESSDPIAWARENESS pfnSetProcessDpiAwareness = - (PFN_SETPROCESSDPIAWARENESS)GetProcAddress(_hUser32, "SetProcessDpiAwarenessInternal"); + (PFN_SETPROCESSDPIAWARENESS)GetProcAddress(user32, "SetProcessDpiAwarenessInternal"); if (pfnSetProcessDpiAwareness == NULL) { if (windisplay_cat.is_debug()) { @@ -908,26 +878,4 @@ lookup_cpu_data() { */ WinGraphicsPipe:: ~WinGraphicsPipe() { - if (_hUser32 != NULL) { - FreeLibrary(_hUser32); - _hUser32 = NULL; - } -} - -bool MyGetProcAddr(HINSTANCE hDLL, FARPROC *pFn, const char *szExportedFnName) { - *pFn = (FARPROC) GetProcAddress(hDLL, szExportedFnName); - if (*pFn == NULL) { - windisplay_cat.error() << "GetProcAddr failed for " << szExportedFnName << ", error=" << GetLastError() < 1)) { + if (_input_devices.size() > 1) { RAWINPUTDEVICE Rid; Rid.usUsagePage = 0x01; Rid.usUsage = 0x02; Rid.dwFlags = 0;// RIDEV_NOLEGACY; // adds HID mouse and also ignores legacy mouse messages Rid.hwndTarget = _hWnd; - pRegisterRawInputDevices(&Rid, 1, sizeof (Rid)); + RegisterRawInputDevices(&Rid, 1, sizeof (Rid)); } // Create a WindowHandle for ourselves @@ -535,10 +537,23 @@ open_window() { // set us as the focus window for keyboard input set_focus(); + // Try initializing the touch function pointers. + static bool initialized = false; + if (!initialized) { + initialized = true; + HMODULE user32 = GetModuleHandleA("user32.dll"); + if (user32) { + // Introduced in Windows 7. + pRegisterTouchWindow = (PFN_REGISTERTOUCHWINDOW)GetProcAddress(user32, "RegisterTouchWindow"); + pGetTouchInputInfo = (PFN_GETTOUCHINPUTINFO)GetProcAddress(user32, "GetTouchInputInfo"); + pCloseTouchInputHandle = (PFN_CLOSETOUCHINPUTHANDLE)GetProcAddress(user32, "CloseTouchInputHandle"); + } + } + // Register for Win7 touch events. -#ifdef HAVE_WIN_TOUCHINPUT - RegisterTouchWindow(_hWnd, 0); -#endif + if (pRegisterTouchWindow != NULL) { + pRegisterTouchWindow(_hWnd, 0); + } return true; } @@ -563,45 +578,35 @@ initialize_input_devices() { GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse"); add_input_device(device); - // Try initializing the Raw Input function pointers. - if (pRegisterRawInputDevices==0) { - HMODULE user32 = LoadLibrary("user32.dll"); - if (user32) { - pRegisterRawInputDevices = (tRegisterRawInputDevices)GetProcAddress(user32,"RegisterRawInputDevices"); - pGetRawInputDeviceList = (tGetRawInputDeviceList) GetProcAddress(user32,"GetRawInputDeviceList"); - pGetRawInputDeviceInfoA = (tGetRawInputDeviceInfoA) GetProcAddress(user32,"GetRawInputDeviceInfoA"); - pGetRawInputData = (tGetRawInputData) GetProcAddress(user32,"GetRawInputData"); - } - } - - if (pRegisterRawInputDevices==0) return; - if (pGetRawInputDeviceList==0) return; - if (pGetRawInputDeviceInfoA==0) return; - if (pGetRawInputData==0) return; - // Get the number of devices. - if (pGetRawInputDeviceList(NULL, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0) + if (GetRawInputDeviceList(NULL, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) != 0) { return; + } // Allocate the array to hold the DeviceList pRawInputDeviceList = (PRAWINPUTDEVICELIST)alloca(sizeof(RAWINPUTDEVICELIST) * nInputDevices); - if (pRawInputDeviceList==0) return; + if (pRawInputDeviceList==0) { + return; + } // Fill the Array - if (pGetRawInputDeviceList(pRawInputDeviceList, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) == -1) + if (GetRawInputDeviceList(pRawInputDeviceList, &nInputDevices, sizeof(RAWINPUTDEVICELIST)) == -1) { return; + } // Loop through all raw devices and find the raw mice for (int i = 0; i < (int)nInputDevices; i++) { if (pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE) { // Fetch information about specified mouse device. UINT nSize; - if (pGetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)0, &nSize) != 0) + if (GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)0, &nSize) != 0) { return; + } char *psName = (char*)alloca(sizeof(TCHAR) * nSize); if (psName == 0) return; - if (pGetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)psName, &nSize) < 0) + if (GetRawInputDeviceInfoA(pRawInputDeviceList[i].hDevice, RIDI_DEVICENAME, (LPVOID)psName, &nSize) < 0) { return; + } // If it's not an RDP mouse, add it to the list of raw mice. if (strncmp(psName,"\\??\\Root#RDP_MOU#0000#",22)!=0) { @@ -1215,31 +1220,25 @@ adjust_z_order(WindowProperties::ZOrder last_z_order, */ void WinGraphicsWindow:: track_mouse_leaving(HWND hwnd) { - // Note: could use _TrackMouseEvent in comctrl32.dll (part of IE 3.0+) which - // emulates TrackMouseEvent on w95, but that requires another 500K of memory - // to hold that DLL, which is lame just to support w95, which probably has - // other issues anyway WinGraphicsPipe *winpipe; DCAST_INTO_V(winpipe, _pipe); - if (winpipe->_pfnTrackMouseEvent != NULL) { - TRACKMOUSEEVENT tme = { - sizeof(TRACKMOUSEEVENT), - TME_LEAVE, - hwnd, - 0 - }; + TRACKMOUSEEVENT tme = { + sizeof(TRACKMOUSEEVENT), + TME_LEAVE, + hwnd, + 0 + }; - // tell win32 to post WM_MOUSELEAVE msgs - BOOL bSucceeded = winpipe->_pfnTrackMouseEvent(&tme); + // tell win32 to post WM_MOUSELEAVE msgs + BOOL bSucceeded = TrackMouseEvent(&tme); - if ((!bSucceeded) && windisplay_cat.is_debug()) { - windisplay_cat.debug() - << "TrackMouseEvent failed!, LastError=" << GetLastError() << endl; - } - - _tracking_mouse_leaving = true; + if (!bSucceeded && windisplay_cat.is_debug()) { + windisplay_cat.debug() + << "TrackMouseEvent failed!, LastError=" << GetLastError() << endl; } + + _tracking_mouse_leaving = true; } /** @@ -2067,15 +2066,16 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { } break; -#ifdef HAVE_WIN_TOUCHINPUT case WM_TOUCH: - _numTouches = LOWORD(wparam); - if(_numTouches > MAX_TOUCHES) - _numTouches = MAX_TOUCHES; - GetTouchInputInfo((HTOUCHINPUT)lparam, _numTouches, _touches, sizeof(TOUCHINPUT)); - CloseTouchInputHandle((HTOUCHINPUT)lparam); + _num_touches = LOWORD(wparam); + if (_num_touches > MAX_TOUCHES) { + _num_touches = MAX_TOUCHES; + } + if (pGetTouchInputInfo != 0) { + pGetTouchInputInfo((HTOUCHINPUT)lparam, _num_touches, _touches, sizeof(TOUCHINPUT)); + pCloseTouchInputHandle((HTOUCHINPUT)lparam); + } break; -#endif } // do custom messages processing if any has been set @@ -2607,7 +2607,7 @@ handle_raw_input(HRAWINPUT hraw) { if (hraw == 0) { return; } - if (pGetRawInputData(hraw, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)) == -1) { + if (GetRawInputData(hraw, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)) == -1) { return; } @@ -2616,7 +2616,7 @@ handle_raw_input(HRAWINPUT hraw) { return; } - if (pGetRawInputData(hraw, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) { + if (GetRawInputData(hraw, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) { return; } @@ -2973,12 +2973,8 @@ bool WinGraphicsWindow::supports_window_procs() const{ * */ bool WinGraphicsWindow:: -is_touch_event(GraphicsWindowProcCallbackData* callbackData){ -#ifdef HAVE_WIN_TOUCHINPUT +is_touch_event(GraphicsWindowProcCallbackData *callbackData) { return callbackData->get_msg() == WM_TOUCH; -#else - return false; -#endif } /** @@ -2987,11 +2983,7 @@ is_touch_event(GraphicsWindowProcCallbackData* callbackData){ */ int WinGraphicsWindow:: get_num_touches(){ -#ifdef HAVE_WIN_TOUCHINPUT - return _numTouches; -#else - return 0; -#endif + return _num_touches; } /** @@ -2999,8 +2991,9 @@ get_num_touches(){ * */ TouchInfo WinGraphicsWindow:: -get_touch_info(int index){ -#ifdef HAVE_WIN_TOUCHINPUT +get_touch_info(int index) { + nassertr(index >= 0 && index < MAX_TOUCHES, TouchInfo()); + TOUCHINPUT ti = _touches[index]; POINT point; point.x = TOUCH_COORD_TO_PIXEL(ti.x); @@ -3013,7 +3006,4 @@ get_touch_info(int index){ ret.set_id(ti.dwID); ret.set_flags(ti.dwFlags); return ret; -#else - return TouchInfo(); -#endif } diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 798218052a..ec7e1217ff 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -34,8 +34,23 @@ typedef struct { int y; int width; int height; -} -WINDOW_METRICS; +} WINDOW_METRICS; + +#if WINVER < 0x0601 +// Not used on Windows XP, but we still need to define it. +typedef struct tagTOUCHINPUT { + LONG x; + LONG y; + HANDLE hSource; + DWORD dwID; + DWORD dwFlags; + DWORD dwMask; + DWORD dwTime; + ULONG_PTR dwExtraInfo; + DWORD cxContact; + DWORD cyContact; +} TOUCHINPUT, *PTOUCHINPUT; +#endif /** * An abstract base class for glGraphicsWindow and dxGraphicsWindow (and, in @@ -177,10 +192,8 @@ private: typedef pset WinProcClasses; WinProcClasses _window_proc_classes; -#ifdef HAVE_WIN_TOUCHINPUT - UINT _numTouches; + UINT _num_touches; TOUCHINPUT _touches[MAX_TOUCHES]; -#endif private: // We need this map to support per-window calls to window_proc(). From b182224463b153420ac4eb1a4ea6c9f86dae7ad5 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 5 Dec 2016 17:22:24 -0500 Subject: [PATCH 09/70] interrogate: fix issues with abstract classes and covariance (fixes EggPolygon constructor) --- dtool/src/cppparser/cppFunctionType.cxx | 9 +++-- dtool/src/cppparser/cppFunctionType.h | 2 +- dtool/src/cppparser/cppStructType.cxx | 54 ++++++++----------------- 3 files changed, 24 insertions(+), 41 deletions(-) diff --git a/dtool/src/cppparser/cppFunctionType.cxx b/dtool/src/cppparser/cppFunctionType.cxx index 371b714c2d..1872ea11f5 100644 --- a/dtool/src/cppparser/cppFunctionType.cxx +++ b/dtool/src/cppparser/cppFunctionType.cxx @@ -326,14 +326,17 @@ as_function_type() { * This is similar to is_equal(), except it is more forgiving: it considers * the functions to be equivalent only if the return type and the types of all * parameters match. + * + * Note that this isn't symmetric to account for covariant return types. */ bool CPPFunctionType:: -is_equivalent_function(const CPPFunctionType &other) const { - if (!_return_type->is_equivalent(*other._return_type)) { +match_virtual_override(const CPPFunctionType &other) const { + if (!_return_type->is_equivalent(*other._return_type) && + !_return_type->is_convertible_to(other._return_type)) { return false; } - if (_flags != other._flags) { + if (((_flags ^ other._flags) & ~(F_override | F_final)) != 0) { return false; } diff --git a/dtool/src/cppparser/cppFunctionType.h b/dtool/src/cppparser/cppFunctionType.h index f08de51e45..1e44681f13 100644 --- a/dtool/src/cppparser/cppFunctionType.h +++ b/dtool/src/cppparser/cppFunctionType.h @@ -84,7 +84,7 @@ public: virtual CPPFunctionType *as_function_type(); - bool is_equivalent_function(const CPPFunctionType &other) const; + bool match_virtual_override(const CPPFunctionType &other) const; CPPIdentifier *_class_owner; diff --git a/dtool/src/cppparser/cppStructType.cxx b/dtool/src/cppparser/cppStructType.cxx index 73712c66ad..afb03dd463 100644 --- a/dtool/src/cppparser/cppStructType.cxx +++ b/dtool/src/cppparser/cppStructType.cxx @@ -378,6 +378,10 @@ is_constructible(const CPPType *given_type) const { } } + if (is_abstract()) { + return false; + } + // Check for a different constructor. CPPFunctionGroup *fgroup = get_constructor(); if (fgroup != (CPPFunctionGroup *)NULL) { @@ -444,6 +448,10 @@ is_destructible() const { */ bool CPPStructType:: is_default_constructible(CPPVisibility min_vis) const { + if (is_abstract()) { + return false; + } + CPPInstance *constructor = get_default_constructor(); if (constructor != (CPPInstance *)NULL) { // It has a default constructor. @@ -498,24 +506,6 @@ is_default_constructible(CPPVisibility min_vis) const { } } - // Check that we don't have pure virtual methods. - CPPScope::Functions::const_iterator fi; - for (fi = _scope->_functions.begin(); - fi != _scope->_functions.end(); - ++fi) { - CPPFunctionGroup *fgroup = (*fi).second; - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - if (inst->_storage_class & CPPInstance::SC_pure_virtual) { - // Here's a pure virtual function. - return false; - } - } - } - return true; } @@ -524,6 +514,10 @@ is_default_constructible(CPPVisibility min_vis) const { */ bool CPPStructType:: is_copy_constructible(CPPVisibility min_vis) const { + if (is_abstract()) { + return false; + } + CPPInstance *constructor = get_copy_constructor(); if (constructor != (CPPInstance *)NULL) { // It has a copy constructor. @@ -581,24 +575,6 @@ is_copy_constructible(CPPVisibility min_vis) const { } } - // Check that we don't have pure virtual methods. - CPPScope::Functions::const_iterator fi; - for (fi = _scope->_functions.begin(); - fi != _scope->_functions.end(); - ++fi) { - CPPFunctionGroup *fgroup = (*fi).second; - CPPFunctionGroup::Instances::const_iterator ii; - for (ii = fgroup->_instances.begin(); - ii != fgroup->_instances.end(); - ++ii) { - CPPInstance *inst = (*ii); - if (inst->_storage_class & CPPInstance::SC_pure_virtual) { - // Here's a pure virtual function. - return false; - } - } - } - return true; } @@ -620,6 +596,10 @@ is_move_constructible(CPPVisibility min_vis) const { return false; } + if (is_abstract()) { + return false; + } + return true; } @@ -1214,7 +1194,7 @@ get_virtual_funcs(VFunctions &funcs) const { CPPFunctionType *new_ftype = new_inst->_type->as_function_type(); assert(new_ftype != (CPPFunctionType *)NULL); - if (new_ftype->is_equivalent_function(*base_ftype)) { + if (new_ftype->match_virtual_override(*base_ftype)) { // It's a match! We now know it's virtual. Erase this function // from the list, so we can add it back in below. funcs.erase(vfi); From 3fa5b6b4ee569425ab99e16e4e1aa55273abc0f4 Mon Sep 17 00:00:00 2001 From: tobspr Date: Tue, 6 Dec 2016 18:42:08 +0100 Subject: [PATCH 10/70] Add prc variable to force image bindings as writeonly (#131) --- panda/src/glstuff/glShaderContext_src.cxx | 5 ++++- panda/src/glstuff/glmisc_src.cxx | 5 +++++ panda/src/glstuff/glmisc_src.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index b02ec341df..528b98804c 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -2486,7 +2486,10 @@ update_shader_texture_bindings(ShaderContext *prev) { bool has_write = param->has_write_access(); input._writable = has_write; - if (has_read && has_write) { + if (gl_force_image_bindings_writeonly) { + access = GL_WRITE_ONLY; + + } else if (has_read && has_write) { access = GL_READ_WRITE; } else if (has_read) { diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index c44a36aaf6..544a5c2c79 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -299,6 +299,11 @@ ConfigVariableBool gl_support_shadow_filter "cards suffered from a broken implementation of the " "shadow map filtering features.")); +ConfigVariableBool gl_force_image_bindings_writeonly + ("gl-force-image-bindings-writeonly", false, + PRC_DESC("Forces all image inputs (not textures!) to be bound as writeonly, " + "to read from an image, rebind it as sampler.")); + ConfigVariableEnum gl_coordinate_system ("gl-coordinate-system", CS_yup_right, PRC_DESC("Which coordinate system to use as the internal " diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index b008aeb8d3..fb8040828f 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -80,6 +80,7 @@ extern ConfigVariableBool gl_fixed_vertex_attrib_locations; extern ConfigVariableBool gl_support_primitive_restart_index; extern ConfigVariableBool gl_support_sampler_objects; extern ConfigVariableBool gl_support_shadow_filter; +extern ConfigVariableBool gl_force_image_bindings_writeonly; extern ConfigVariableEnum gl_coordinate_system; extern EXPCL_GL void CLP(init_classes)(); From e778c529b2afb94024c2aa01912b15c0d93fe83c Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 7 Dec 2016 00:42:44 +0100 Subject: [PATCH 11/70] Implement Python 3.6 fspath protocol; allow passing a pathlib.Path wherever Filename is expected The Python 3.6 fspath protocol allows passing Filename objects into any Python standard library calls that take a path. --- dtool/src/dtoolutil/filename.I | 25 +++--- dtool/src/dtoolutil/filename.h | 13 ++-- panda/src/express/filename_ext.cxx | 119 +++++++++++++++++++++++++++++ panda/src/express/filename_ext.h | 3 + 4 files changed, 145 insertions(+), 15 deletions(-) diff --git a/dtool/src/dtoolutil/filename.I b/dtool/src/dtoolutil/filename.I index 9ab46bf501..9bc23dfca3 100644 --- a/dtool/src/dtoolutil/filename.I +++ b/dtool/src/dtoolutil/filename.I @@ -38,7 +38,6 @@ Filename(const char *filename) { (*this) = filename; } - /** * */ @@ -84,6 +83,20 @@ Filename(Filename &&from) NOEXCEPT : } #endif // USE_MOVE_SEMANTICS +/** + * Creates an empty Filename. + */ +INLINE Filename:: +Filename() : + _dirname_end(0), + _basename_start(0), + _basename_end(string::npos), + _extension_start(string::npos), + _hash_start(string::npos), + _hash_end(string::npos), + _flags(0) { +} + /** * */ @@ -155,14 +168,6 @@ pattern_filename(const string &filename) { return result; } -/** - * - */ -INLINE Filename:: -~Filename() { -} - - /** * */ @@ -233,7 +238,7 @@ operator = (string &&filename) NOEXCEPT { */ INLINE Filename &Filename:: operator = (Filename &&from) NOEXCEPT { - _filename = MOVE(from._filename); + _filename = move(from._filename); _dirname_end = from._dirname_end; _basename_start = from._basename_start; _basename_end = from._basename_end; diff --git a/dtool/src/dtoolutil/filename.h b/dtool/src/dtoolutil/filename.h index 378bf4fe1c..e0c4b8c414 100644 --- a/dtool/src/dtoolutil/filename.h +++ b/dtool/src/dtoolutil/filename.h @@ -55,20 +55,22 @@ public: }; INLINE Filename(const char *filename); - -PUBLISHED: - INLINE Filename(const string &filename = ""); + INLINE Filename(const string &filename); INLINE Filename(const wstring &filename); INLINE Filename(const Filename ©); - Filename(const Filename &dirname, const Filename &basename); - INLINE ~Filename(); #ifdef USE_MOVE_SEMANTICS INLINE Filename(string &&filename) NOEXCEPT; INLINE Filename(Filename &&from) NOEXCEPT; #endif +PUBLISHED: + INLINE Filename(); + Filename(const Filename &dirname, const Filename &basename); + #ifdef HAVE_PYTHON + EXTENSION(Filename(PyObject *path)); + EXTENSION(PyObject *__reduce__(PyObject *self) const); #endif @@ -118,6 +120,7 @@ PUBLISHED: INLINE char operator [] (size_t n) const; EXTENSION(PyObject *__repr__() const); + EXTENSION(PyObject *__fspath__() const); INLINE string substr(size_t begin) const; INLINE string substr(size_t begin, size_t end) const; diff --git a/panda/src/express/filename_ext.cxx b/panda/src/express/filename_ext.cxx index 70afd0d07d..1c9bf78e7e 100644 --- a/panda/src/express/filename_ext.cxx +++ b/panda/src/express/filename_ext.cxx @@ -14,6 +14,115 @@ #include "filename_ext.h" #ifdef HAVE_PYTHON + +#ifndef CPPPARSER +extern Dtool_PyTypedObject Dtool_Filename; +#endif // CPPPARSER + +/** + * Constructs a Filename object from a str, bytes object, or os.PathLike. + */ +void Extension:: +__init__(PyObject *path) { + nassertv(path != NULL); + nassertv(_this != NULL); + + Py_ssize_t length; + + if (PyUnicode_CheckExact(path)) { + wchar_t *data; +#if PY_VERSION_HEX >= 0x03020000 + data = PyUnicode_AsWideCharString(path, &length); +#else + length = PyUnicode_GET_SIZE(path); + data = (wchar_t *)alloca(sizeof(wchar_t) * (length + 1)); + PyUnicode_AsWideChar((PyUnicodeObject *)path, data, length); +#endif + (*_this) = wstring(data, length); + +#if PY_VERSION_HEX >= 0x03020000 + PyMem_Free(data); +#endif + return; + } + + if (PyBytes_CheckExact(path)) { + char *data; + PyBytes_AsStringAndSize(path, &data, &length); + (*_this) = string(data, length); + return; + } + + if (Py_TYPE(path) == &Dtool_Filename._PyType) { + // Copy constructor. + (*_this) = *((Filename *)((Dtool_PyInstDef *)path)->_ptr_to_object); + return; + } + + PyObject *path_str; + +#if PY_VERSION_HEX >= 0x03060000 + // It must be an os.PathLike object. Check for an __fspath__ method. + PyObject *fspath = PyObject_GetAttrString((PyObject *)Py_TYPE(path), "__fspath__"); + if (fspath == NULL) { + PyErr_Format(PyExc_TypeError, "expected str, bytes or os.PathLike object, not %s", Py_TYPE(path)->tp_name); + return; + } + + path_str = PyObject_CallFunctionObjArgs(fspath, path, NULL); + Py_DECREF(fspath); +#else + // There is no standard path protocol before Python 3.6, but let's try and + // support taking pathlib paths anyway. We don't version check this to + // allow people to use backports of the pathlib module. + if (PyObject_HasAttrString(path, "_format_parsed_parts")) { + path_str = PyObject_Str(path); + } else { +#if PY_VERSION_HEX >= 0x03040000 + PyErr_Format(PyExc_TypeError, "expected str, bytes, Path or Filename object, not %s", Py_TYPE(path)->tp_name); +#elif PY_MAJOR_VERSION >= 3 + PyErr_Format(PyExc_TypeError, "expected str, bytes or Filename object, not %s", Py_TYPE(path)->tp_name); +#else + PyErr_Format(PyExc_TypeError, "expected str or unicode object, not %s", Py_TYPE(path)->tp_name); +#endif + return; + } +#endif + + if (path_str == NULL) { + return; + } + + if (PyUnicode_CheckExact(path_str)) { + wchar_t *data; +#if PY_VERSION_HEX >= 0x03020000 + data = PyUnicode_AsWideCharString(path_str, &length); +#else + length = PyUnicode_GET_SIZE(path_str); + data = (wchar_t *)alloca(sizeof(wchar_t) * (length + 1)); + PyUnicode_AsWideChar((PyUnicodeObject *)path_str, data, length); +#endif + (*_this) = Filename::from_os_specific_w(wstring(data, length)); + +#if PY_VERSION_HEX >= 0x03020000 + PyMem_Free(data); +#endif + + } else if (PyBytes_CheckExact(path_str)) { + char *data; + PyBytes_AsStringAndSize(path_str, &data, &length); + (*_this) = Filename::from_os_specific(string(data, length)); + + } else { +#if PY_MAJOR_VERSION >= 3 + PyErr_Format(PyExc_TypeError, "expected str or bytes object, not %s", Py_TYPE(path_str)->tp_name); +#else + PyErr_Format(PyExc_TypeError, "expected str or unicode object, not %s", Py_TYPE(path_str)->tp_name); +#endif + } + Py_DECREF(path_str); +} + /** * This special Python method is implement to provide support for the pickle * module. @@ -62,6 +171,16 @@ __repr__() const { return result; } +/** + * Allows a Filename object to be passed to any Python function that accepts + * an os.PathLike object. + */ +PyObject *Extension:: +__fspath__() const { + wstring filename = _this->to_os_specific_w(); + return PyUnicode_FromWideChar(filename.data(), (Py_ssize_t)filename.size()); +} + /** * This variant on scan_directory returns a Python list of strings on success, * or None on failure. diff --git a/panda/src/express/filename_ext.h b/panda/src/express/filename_ext.h index c1d5869ec7..1ebeaacc52 100644 --- a/panda/src/express/filename_ext.h +++ b/panda/src/express/filename_ext.h @@ -29,8 +29,11 @@ template<> class Extension : public ExtensionBase { public: + void __init__(PyObject *path); + PyObject *__reduce__(PyObject *self) const; PyObject *__repr__() const; + PyObject *__fspath__() const; PyObject *scan_directory() const; }; From ceee5e9df95d3301ed9d329491737f0e39321a86 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 7 Dec 2016 19:32:01 +0100 Subject: [PATCH 12/70] Show texture names in glBindTexture() calls in spam output --- panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index dc2c0c45e6..8c355cbb03 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -6188,7 +6188,7 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z, if (GLCAT.is_spam()) { GLCAT.spam() - << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n"; + << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << "): " << *tex << "\n"; } } @@ -11365,7 +11365,7 @@ apply_texture(CLP(TextureContext) *gtc) { glBindTexture(target, gtc->_index); if (GLCAT.is_spam()) { GLCAT.spam() - << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n"; + << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << "): " << *gtc->get_texture() << "\n"; } report_my_gl_errors(); @@ -11663,7 +11663,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { if (GLCAT.is_spam()) { GLCAT.spam() - << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n"; + << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << "): " << *tex << "\n"; } } @@ -12636,14 +12636,14 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { } #endif + Texture *tex = gtc->get_texture(); + glBindTexture(target, gtc->_index); if (GLCAT.is_spam()) { GLCAT.spam() - << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << ")\n"; + << "glBindTexture(0x" << hex << target << dec << ", " << gtc->_index << "): " << *tex << "\n"; } - Texture *tex = gtc->get_texture(); - GLint wrap_u, wrap_v, wrap_w; GLint minfilter, magfilter; GLfloat border_color[4]; From b1d61b7b10117f8ee0fec99027f57240af39c046 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 7 Dec 2016 19:32:44 +0100 Subject: [PATCH 13/70] Fix back-to-front sorting with gl-coordinate-system set to a custom value --- panda/src/display/graphicsStateGuardian.cxx | 4 ++++ panda/src/display/graphicsStateGuardian.h | 2 +- panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 10 ---------- panda/src/glstuff/glGraphicsStateGuardian_src.h | 2 -- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 67fbdb2f6c..fee041f57a 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -147,6 +147,10 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _coordinate_system = CS_invalid; _internal_transform = TransformState::make_identity(); + if (_internal_coordinate_system == CS_default) { + _internal_coordinate_system = get_default_coordinate_system(); + } + set_coordinate_system(get_default_coordinate_system()); _data_reader = (GeomVertexDataPipelineReader *)NULL; diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 825b03286d..f8c9dabe6b 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -322,7 +322,7 @@ public: virtual void set_state_and_transform(const RenderState *state, const TransformState *transform); - virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const; + PN_stdfloat compute_distance_to(const LPoint3 &point) const; virtual void clear(DrawableRegion *clearable); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 8c355cbb03..80719c2e69 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -6024,16 +6024,6 @@ make_geom_munger(const RenderState *state, Thread *current_thread) { return GeomMunger::register_munger(munger, current_thread); } -/** - * This function will compute the distance to the indicated point, assumed to - * be in eye coordinates, from the camera plane. The point is assumed to be - * in the GSG's internal coordinate system. - */ -PN_stdfloat CLP(GraphicsStateGuardian):: -compute_distance_to(const LPoint3 &point) const { - return -point[2]; -} - /** * Copy the pixels within the indicated display region from the framebuffer * into texture memory. diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index fe8cff8b59..7659ee13e5 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -358,8 +358,6 @@ public: virtual PT(GeomMunger) make_geom_munger(const RenderState *state, Thread *current_thread); - virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const; - virtual void clear(DrawableRegion *region); virtual bool framebuffer_copy_to_texture From 83d54bcdafc9ba5ed9108e8f0619544f4d275c75 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 7 Dec 2016 22:57:53 +0100 Subject: [PATCH 14/70] Try to preserve refresh rate when switching display mode on Windows --- doc/ReleaseNotes | 1 + panda/src/windisplay/winGraphicsWindow.cxx | 27 +++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index b7462a97d6..a288196f72 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -48,6 +48,7 @@ This issue fixes several bugs that were still found in 1.9.2. * Fix exception when trying to pickle NodePathCollection objects * Fix error when trying to raise vectors to a power * GLSL: fix error when legacy matrix generator inputs are mat3 +* Now tries to preserve refresh rate when switching fullscreen on Windows ------------------------ RELEASE 1.9.2 ------------------------ diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index f270a70f61..0f7e33dc75 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -2357,7 +2357,15 @@ hide_or_show_cursor(bool hide_cursor) { bool WinGraphicsWindow:: find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp, DEVMODE &dm) { + + // Get the current mode. We'll try to match the refresh rate. + DEVMODE cur_dm; + ZeroMemory(&cur_dm, sizeof(cur_dm)); + cur_dm.dmSize = sizeof(cur_dm); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &cur_dm); + int modenum = 0; + int saved_modenum = -1; while (1) { ZeroMemory(&dm, sizeof(dm)); @@ -2369,11 +2377,28 @@ find_acceptable_display_mode(DWORD dwWidth, DWORD dwHeight, DWORD bpp, if ((dm.dmPelsWidth == dwWidth) && (dm.dmPelsHeight == dwHeight) && (dm.dmBitsPerPel == bpp)) { - return true; + // If this also matches in refresh rate, we're done here. Otherwise, + // save this as a second choice for later. + if (dm.dmDisplayFrequency == cur_dm.dmDisplayFrequency) { + return true; + } else if (saved_modenum == -1) { + saved_modenum = modenum; + } } modenum++; } + // Failed to find an exact match, but we do have a match that didn't match + // the refresh rate. + if (saved_modenum != -1) { + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + + if (EnumDisplaySettings(NULL, saved_modenum, &dm)) { + return true; + } + } + return false; } From a1338b9ac6171b2fc37f088b8130e5d22b378b54 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 7 Dec 2016 23:00:06 +0100 Subject: [PATCH 15/70] Backport to 1.9: fix for distance sorting with gl-coordinate-system changed --- doc/ReleaseNotes | 1 + panda/src/display/graphicsStateGuardian.cxx | 4 ++++ panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 13 ------------- panda/src/glstuff/glGraphicsStateGuardian_src.h | 2 -- 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index a288196f72..03d2dcf92a 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -49,6 +49,7 @@ This issue fixes several bugs that were still found in 1.9.2. * Fix error when trying to raise vectors to a power * GLSL: fix error when legacy matrix generator inputs are mat3 * Now tries to preserve refresh rate when switching fullscreen on Windows +* Fix back-to-front sorting when gl-coordinate-system is changed ------------------------ RELEASE 1.9.2 ------------------------ diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 0a2ae03c1e..d3557fa390 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -148,6 +148,10 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _coordinate_system = CS_invalid; _internal_transform = TransformState::make_identity(); + if (internal_coordinate_system == CS_default) { + _internal_coordinate_system = get_default_coordinate_system(); + } + set_coordinate_system(get_default_coordinate_system()); _data_reader = (GeomVertexDataPipelineReader *)NULL; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index b70552a032..575d6e202c 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -5485,19 +5485,6 @@ make_geom_munger(const RenderState *state, Thread *current_thread) { return GeomMunger::register_munger(munger, current_thread); } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::compute_distance_to -// Access: Public, Virtual -// Description: This function will compute the distance to the -// indicated point, assumed to be in eye coordinates, -// from the camera plane. The point is assumed to be -// in the GSG's internal coordinate system. -//////////////////////////////////////////////////////////////////// -PN_stdfloat CLP(GraphicsStateGuardian):: -compute_distance_to(const LPoint3 &point) const { - return -point[2]; -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::framebuffer_copy_to_texture // Access: Public, Virtual diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index f8ec534eb2..27fd475724 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -336,8 +336,6 @@ public: virtual PT(GeomMunger) make_geom_munger(const RenderState *state, Thread *current_thread); - virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const; - virtual void clear(DrawableRegion *region); virtual bool framebuffer_copy_to_texture From 32377cb618207f5a5a294934d9c2310d6fb8635e Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 7 Dec 2016 23:04:15 +0100 Subject: [PATCH 16/70] interrogate: fix to allow pointers to forcetyped classes --- dtool/src/interrogate/interfaceMakerPythonNative.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index d4eea3fdff..a844771fa6 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -6142,7 +6142,7 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const); } - } else if (TypeManager::is_struct(orig_type->as_pointer_type()->_pointing_at)) { + } else if (TypeManager::is_struct(orig_type->remove_pointer())) { TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); const InterrogateType &itype = idb->get_type(type_index); @@ -6749,6 +6749,8 @@ is_cpp_type_legal(CPPType *in_ctype) { return true; } else if (TypeManager::is_pointer_to_simple(type)) { return true; + } else if (builder.in_forcetype(type->get_local_name(&parser))) { + return true; } else if (TypeManager::is_exported(type)) { return true; } else if (TypeManager::is_pointer_to_PyObject(in_ctype)) { From c422f5952fdf4a11ba19a83c6431f13bed2aa22c Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 8 Dec 2016 23:21:01 +0100 Subject: [PATCH 17/70] Increase default alignment to 2x word size, make DeletedBufferChain allocations more efficient NB. NeverFreeMemory no longer performs alignment. This fixes the Bullet crash on Win64. Need to check Win32. --- dtool/src/dtoolbase/deletedBufferChain.cxx | 11 +++++++++-- dtool/src/dtoolbase/deletedBufferChain.h | 6 +----- dtool/src/dtoolbase/memoryHook.I | 10 ++++++---- dtool/src/dtoolbase/neverFreeMemory.I | 2 ++ dtool/src/dtoolbase/neverFreeMemory.cxx | 10 +++------- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/dtool/src/dtoolbase/deletedBufferChain.cxx b/dtool/src/dtoolbase/deletedBufferChain.cxx index 89f056219c..122edf8837 100644 --- a/dtool/src/dtoolbase/deletedBufferChain.cxx +++ b/dtool/src/dtoolbase/deletedBufferChain.cxx @@ -39,7 +39,7 @@ allocate(size_t size, TypeHandle type_handle) { assert(size <= _buffer_size); // Determine how much space to allocate. - const size_t alloc_size = _buffer_size + flag_reserved_bytes; + const size_t alloc_size = _buffer_size + flag_reserved_bytes + MemoryHook::get_memory_alignment() - 1; ObjectNode *obj; @@ -69,7 +69,10 @@ allocate(size_t size, TypeHandle type_handle) { // If we get here, the deleted_chain is empty; we have to allocate a new // object from the system pool. - obj = (ObjectNode *)NeverFreeMemory::alloc(alloc_size); + // Allocate memory, and make sure the object starts at the proper alignment. + void *mem = NeverFreeMemory::alloc(alloc_size); + intptr_t pad = ((intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment(); + obj = (ObjectNode *)((uintptr_t)mem + pad); #ifdef USE_DELETEDCHAINFLAG obj->_flag = DCF_alive; @@ -77,6 +80,10 @@ allocate(size_t size, TypeHandle type_handle) { void *ptr = node_to_buffer(obj); +#ifdef _DEBUG + assert(((uintptr_t)ptr % MemoryHook::get_memory_alignment()) == 0); +#endif + #ifdef DO_MEMORY_USAGE type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size); #endif // DO_MEMORY_USAGE diff --git a/dtool/src/dtoolbase/deletedBufferChain.h b/dtool/src/dtoolbase/deletedBufferChain.h index 6df4583ee8..8f82c1abbc 100644 --- a/dtool/src/dtoolbase/deletedBufferChain.h +++ b/dtool/src/dtoolbase/deletedBufferChain.h @@ -95,12 +95,8 @@ private: // Without DELETEDCHAINFLAG, we don't even store the _flag member at all. static const size_t flag_reserved_bytes = 0; -#elif defined(LINMATH_ALIGN) - // With SSE2 alignment, we need all 16 bytes to preserve alignment. - static const size_t flag_reserved_bytes = 16; - #else - // Otherwise, we only need enough space for the Integer itself. + // Otherwise, we need space for the integer. static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer); #endif // USE_DELETEDCHAINFLAG diff --git a/dtool/src/dtoolbase/memoryHook.I b/dtool/src/dtoolbase/memoryHook.I index c54e34c1f3..09f89cc9df 100644 --- a/dtool/src/dtoolbase/memoryHook.I +++ b/dtool/src/dtoolbase/memoryHook.I @@ -45,8 +45,9 @@ get_memory_alignment() { // don't strictly have to align *everything*, but it's just easier to do so. const size_t alignment_size = 16; #else - // Otherwise, use word alignment. - const size_t alignment_size = sizeof(void *); + // Otherwise, align to two words. This seems to be pretty standard to the + // point where some code may rely on this being the case. + const size_t alignment_size = sizeof(void *) * 2; #endif return alignment_size; } @@ -72,8 +73,9 @@ get_header_reserved_bytes() { static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t); #else - // If we're not aligning, we just need space for the word itself. - static const size_t header_reserved_bytes = sizeof(size_t); + // Virtually all allocators align to two words, so we make sure we preserve + // that alignment for the benefit of anyone who relies upon that. + static const size_t header_reserved_bytes = sizeof(void *) * 2; #endif return header_reserved_bytes; diff --git a/dtool/src/dtoolbase/neverFreeMemory.I b/dtool/src/dtoolbase/neverFreeMemory.I index 33e5b5851c..2156209616 100644 --- a/dtool/src/dtoolbase/neverFreeMemory.I +++ b/dtool/src/dtoolbase/neverFreeMemory.I @@ -14,6 +14,8 @@ /** * Returns a pointer to a newly-allocated block of memory of the indicated * size. + * + * Please note that the resulting pointer is not aligned to any boundary. */ INLINE void *NeverFreeMemory:: alloc(size_t size) { diff --git a/dtool/src/dtoolbase/neverFreeMemory.cxx b/dtool/src/dtoolbase/neverFreeMemory.cxx index 1ec800a749..fd10b683d8 100644 --- a/dtool/src/dtoolbase/neverFreeMemory.cxx +++ b/dtool/src/dtoolbase/neverFreeMemory.cxx @@ -39,13 +39,9 @@ void *NeverFreeMemory:: ns_alloc(size_t size) { _lock.acquire(); - // We always allocate integer multiples of this many bytes, to guarantee - // this minimum alignment. - static const size_t alignment_size = MemoryHook::get_memory_alignment(); - - // Round up to the next alignment_size. - size = ((size + alignment_size - 1) / alignment_size) * alignment_size; - + //NB: we no longer do alignment here. The only class that uses this is + // DeletedBufferChain, and we can do the alignment potentially more + // efficiently there since we don't end up overallocating as much. _total_used += size; // Look for a page that has sufficient space remaining. From 9eb04a533d7b16fe5c044e47a6c156cc0f3b5043 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 9 Dec 2016 01:41:32 +0100 Subject: [PATCH 18/70] More texture load/store performance optimisations --- panda/src/gobj/texture.cxx | 53 ++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 8fa7226806..76530db95b 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -7729,10 +7729,11 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, // Most common case: one byte per pixel, and the source image shows a // maxval of 255. No scaling is necessary. Because this is such a common // case, we break it out per component for best performance. + const xel *array = pnmimage.get_array(); switch (num_components) { case 1: for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + const xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); } @@ -7742,9 +7743,10 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, case 2: if (img_has_alpha) { + const xelval *alpha = pnmimage.get_alpha_array(); for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); - xelval *alpha_row = pnmimage.alpha_row(j); + const xel *row = array + j * x_size; + const xelval *alpha_row = alpha + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)alpha_row[i]; @@ -7753,7 +7755,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, } } else { for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + const xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)255; @@ -7765,7 +7767,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, case 3: for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + const xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)PPM_GETG(row[i]); @@ -7777,9 +7779,10 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, case 4: if (img_has_alpha) { + const xelval *alpha = pnmimage.get_alpha_array(); for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); - xelval *alpha_row = pnmimage.alpha_row(j); + const xel *row = array + j * x_size; + const xelval *alpha_row = alpha + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)PPM_GETG(row[i]); @@ -7790,7 +7793,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, } } else { for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + const xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)PPM_GETG(row[i]); @@ -7813,7 +7816,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, for (int j = y_size-1; j >= 0; j--) { for (int i = 0; i < x_size; i++) { if (is_grayscale) { - store_unscaled_short(p, pnmimage.get_gray_val(i, j)); + store_unscaled_short(p, pnmimage.get_gray_val(i, j)); } else { store_unscaled_short(p, pnmimage.get_blue_val(i, j)); store_unscaled_short(p, pnmimage.get_green_val(i, j)); @@ -7979,11 +7982,13 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, const unsigned char *p = &image[idx]; if (component_width == 1) { + xel *array = pnmimage.get_array(); if (is_grayscale) { if (has_alpha) { + xelval *alpha = pnmimage.get_alpha_array(); for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); - xelval *alpha_row = pnmimage.alpha_row(j); + xel *row = array + j * x_size; + xelval *alpha_row = alpha + j * x_size; for (int i = 0; i < x_size; i++) { PPM_PUTB(row[i], *p++); alpha_row[i] = *p++; @@ -7991,7 +7996,7 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, } } else { for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { PPM_PUTB(row[i], *p++); } @@ -7999,9 +8004,10 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, } } else { if (has_alpha) { + xelval *alpha = pnmimage.get_alpha_array(); for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); - xelval *alpha_row = pnmimage.alpha_row(j); + xel *row = array + j * x_size; + xelval *alpha_row = alpha + j * x_size; for (int i = 0; i < x_size; i++) { PPM_PUTB(row[i], *p++); PPM_PUTG(row[i], *p++); @@ -8011,7 +8017,7 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, } } else { for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { PPM_PUTB(row[i], *p++); PPM_PUTG(row[i], *p++); @@ -8932,13 +8938,20 @@ compare_images(const PNMImage &a, const PNMImage &b) { nassertr(a.get_x_size() == b.get_x_size() && a.get_y_size() == b.get_y_size(), false); + const xel *a_array = a.get_array(); + const xel *b_array = b.get_array(); + const xelval *a_alpha = a.get_alpha_array(); + const xelval *b_alpha = b.get_alpha_array(); + + int x_size = a.get_x_size(); + int delta = 0; for (int yi = 0; yi < a.get_y_size(); ++yi) { - xel *a_row = a.row(yi); - xel *b_row = b.row(yi); - xelval *a_alpha_row = a.alpha_row(yi); - xelval *b_alpha_row = b.alpha_row(yi); - for (int xi = 0; xi < a.get_x_size(); ++xi) { + const xel *a_row = a_array + yi * x_size; + const xel *b_row = b_array + yi * x_size; + const xelval *a_alpha_row = a_alpha + yi * x_size; + const xelval *b_alpha_row = b_alpha + yi * x_size; + for (int xi = 0; xi < x_size; ++xi) { delta += abs(PPM_GETR(a_row[xi]) - PPM_GETR(b_row[xi])); delta += abs(PPM_GETG(a_row[xi]) - PPM_GETG(b_row[xi])); delta += abs(PPM_GETB(a_row[xi]) - PPM_GETB(b_row[xi])); From b21e8fdf3216b9a18d7f2edef9fc5ce5590f9969 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 11 Dec 2016 15:22:40 +0100 Subject: [PATCH 19/70] COW performance tweaks; also somehow fixes Bullet soft body issue --- .../putil/cachedTypedWritableReferenceCount.I | 19 +++- .../putil/cachedTypedWritableReferenceCount.h | 3 +- panda/src/putil/copyOnWriteObject.cxx | 17 ++++ panda/src/putil/copyOnWriteObject.h | 3 + panda/src/putil/copyOnWritePointer.I | 97 ++++++++++++++++--- panda/src/putil/copyOnWritePointer.cxx | 28 +++--- panda/src/putil/copyOnWritePointer.h | 14 ++- 7 files changed, 145 insertions(+), 36 deletions(-) diff --git a/panda/src/putil/cachedTypedWritableReferenceCount.I b/panda/src/putil/cachedTypedWritableReferenceCount.I index 050c95eb3f..1d60f9a614 100644 --- a/panda/src/putil/cachedTypedWritableReferenceCount.I +++ b/panda/src/putil/cachedTypedWritableReferenceCount.I @@ -126,7 +126,7 @@ cache_ref() const { #endif ref(); - AtomicAdjust::inc(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count); + AtomicAdjust::inc(_cache_ref_count); } /** @@ -147,7 +147,7 @@ cache_unref() const { // you can't use PointerTo's? nassertr(_cache_ref_count > 0, 0); - AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count); + AtomicAdjust::dec(_cache_ref_count); return ReferenceCount::unref(); } @@ -164,6 +164,19 @@ test_ref_count_integrity() const { #endif } +/** + * Decrements the cache reference count without affecting the normal reference + * count. Don't use this. + */ +INLINE void CachedTypedWritableReferenceCount:: +cache_ref_only() const { +#ifdef _DEBUG + nassertv(test_ref_count_integrity()); +#endif + + AtomicAdjust::inc(_cache_ref_count); +} + /** * Decrements the cache reference count without affecting the normal reference * count. Intended to be called by derived classes only, presumably to @@ -180,7 +193,7 @@ cache_unref_only() const { // you can't use PointerTo's? nassertv(_cache_ref_count > 0); - AtomicAdjust::dec(((CachedTypedWritableReferenceCount *)this)->_cache_ref_count); + AtomicAdjust::dec(_cache_ref_count); } /** diff --git a/panda/src/putil/cachedTypedWritableReferenceCount.h b/panda/src/putil/cachedTypedWritableReferenceCount.h index 15772048dd..7420253fcb 100644 --- a/panda/src/putil/cachedTypedWritableReferenceCount.h +++ b/panda/src/putil/cachedTypedWritableReferenceCount.h @@ -47,11 +47,12 @@ PUBLISHED: MAKE_PROPERTY(cache_ref_count, get_cache_ref_count); protected: + INLINE void cache_ref_only() const; INLINE void cache_unref_only() const; bool do_test_ref_count_integrity() const; private: - AtomicAdjust::Integer _cache_ref_count; + mutable AtomicAdjust::Integer _cache_ref_count; public: static TypeHandle get_class_type() { diff --git a/panda/src/putil/copyOnWriteObject.cxx b/panda/src/putil/copyOnWriteObject.cxx index 0faa2f23ce..172f354319 100644 --- a/panda/src/putil/copyOnWriteObject.cxx +++ b/panda/src/putil/copyOnWriteObject.cxx @@ -35,4 +35,21 @@ unref() const { } return is_zero; } + +/** + * Explicitly increments the cache reference count only. Don't use this. + * + * In the case of a CopyOnWriteObject, when the reference count decrements + * down to the cache reference count, the object is implicitly unlocked. + */ +void CopyOnWriteObject:: +cache_ref_only() const { + MutexHolder holder(_lock_mutex); + CachedTypedWritableReferenceCount::cache_ref_only(); + if (get_ref_count() == get_cache_ref_count()) { + ((CopyOnWriteObject *)this)->_lock_status = LS_unlocked; + ((CopyOnWriteObject *)this)->_locking_thread = NULL; + ((CopyOnWriteObject *)this)->_lock_cvar.notify(); + } +} #endif // COW_THREADED diff --git a/panda/src/putil/copyOnWriteObject.h b/panda/src/putil/copyOnWriteObject.h index 8cada6bfd7..12ea5baf24 100644 --- a/panda/src/putil/copyOnWriteObject.h +++ b/panda/src/putil/copyOnWriteObject.h @@ -49,6 +49,9 @@ PUBLISHED: virtual bool unref() const; INLINE void cache_ref() const; INLINE bool cache_unref() const; + +public: + void cache_ref_only() const; #endif // COW_THREADED protected: diff --git a/panda/src/putil/copyOnWritePointer.I b/panda/src/putil/copyOnWritePointer.I index 98a0987791..a44731bcbc 100644 --- a/panda/src/putil/copyOnWritePointer.I +++ b/panda/src/putil/copyOnWritePointer.I @@ -74,23 +74,58 @@ INLINE CopyOnWritePointer:: * */ INLINE CopyOnWritePointer:: -CopyOnWritePointer(CopyOnWritePointer &&move) NOEXCEPT : - _cow_object(move._cow_object) +CopyOnWritePointer(CopyOnWritePointer &&from) NOEXCEPT : + _cow_object(from._cow_object) { // Steal the other's reference count. - move._cow_object = (CopyOnWriteObject *)NULL; + from._cow_object = (CopyOnWriteObject *)NULL; +} + +/** + * + */ +INLINE CopyOnWritePointer:: +CopyOnWritePointer(PointerTo &&from) NOEXCEPT : + _cow_object(from.p()) +{ + // Steal the other's reference count, but because it is a regular pointer, + // we do need to include the cache reference count. + if (_cow_object != (CopyOnWriteObject *)NULL) { + _cow_object->cache_ref_only(); + } + from.cheat() = NULL; } /** * */ INLINE void CopyOnWritePointer:: -operator = (CopyOnWritePointer &&move) NOEXCEPT { +operator = (CopyOnWritePointer &&from) NOEXCEPT { // Protect against self-move-assignment. - if (move._cow_object != _cow_object) { + if (from._cow_object != _cow_object) { CopyOnWriteObject *old_object = _cow_object; - _cow_object = move._cow_object; - move._cow_object = NULL; + _cow_object = from._cow_object; + from._cow_object = NULL; + + if (old_object != (CopyOnWriteObject *)NULL) { + cache_unref_delete(old_object); + } + } +} + +/** + * + */ +INLINE void CopyOnWritePointer:: +operator = (PointerTo &&from) NOEXCEPT { + if (from.p() != _cow_object) { + CopyOnWriteObject *old_object = _cow_object; + + // Steal the other's reference count, but because it is a regular pointer, + // we do need to include the cache reference count. + _cow_object = from.p(); + _cow_object->cache_ref_only(); + from.cheat() = NULL; if (old_object != (CopyOnWriteObject *)NULL) { cache_unref_delete(old_object); @@ -262,20 +297,60 @@ operator = (To *object) { */ template INLINE CopyOnWritePointerTo:: -CopyOnWritePointerTo(CopyOnWritePointerTo &&move) NOEXCEPT : - CopyOnWritePointer((CopyOnWritePointer &&)move) +CopyOnWritePointerTo(CopyOnWritePointerTo &&from) NOEXCEPT : + CopyOnWritePointer((CopyOnWritePointer &&)from) { } #endif // CPPPARSER +#ifndef CPPPARSER +/** + * + */ +template +INLINE CopyOnWritePointerTo:: +CopyOnWritePointerTo(PointerTo &&from) NOEXCEPT { + // Steal the other's reference count, but because it is a regular pointer, + // we do need to include the cache reference count. + _cow_object = from.p(); + if (_cow_object != (CopyOnWriteObject *)NULL) { + _cow_object->cache_ref_only(); + } + from.cheat() = NULL; +} +#endif // CPPPARSER + #ifndef CPPPARSER /** * */ template INLINE void CopyOnWritePointerTo:: -operator = (CopyOnWritePointerTo &&move) NOEXCEPT { - CopyOnWritePointer::operator = ((CopyOnWritePointer &&)move); +operator = (CopyOnWritePointerTo &&from) NOEXCEPT { + CopyOnWritePointer::operator = ((CopyOnWritePointer &&)from); +} +#endif // CPPPARSER + +#ifndef CPPPARSER +/** + * + */ +template +INLINE void CopyOnWritePointerTo:: +operator = (PointerTo &&from) NOEXCEPT { + if (from.p() != _cow_object) { + CopyOnWriteObject *old_object = _cow_object; + + // Steal the other's reference count, but because it is a regular pointer, + // we do need to include the cache reference count. + _cow_object = from.p(); + _cow_object->cache_ref_only(); + from.cheat() = NULL; + + if (old_object != (CopyOnWriteObject *)NULL) { + cache_unref_delete(old_object); + } + } } #endif // CPPPARSER #endif // USE_MOVE_SEMANTICS diff --git a/panda/src/putil/copyOnWritePointer.cxx b/panda/src/putil/copyOnWritePointer.cxx index de0a2e8abf..e2396e84a9 100644 --- a/panda/src/putil/copyOnWritePointer.cxx +++ b/panda/src/putil/copyOnWritePointer.cxx @@ -90,19 +90,17 @@ get_write_pointer() { } PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy(); + _cow_object->CachedTypedWritableReferenceCount::cache_unref(); + _cow_object->_lock_mutex.release(); - // We can't call cache_unref_delete, because we hold the lock. - if (!_cow_object->CachedTypedWritableReferenceCount::cache_unref()) { - _cow_object->_lock_mutex.release(); - delete _cow_object; - } else { - _cow_object->_lock_mutex.release(); - } + MutexHolder holder(new_object->_lock_mutex); _cow_object = new_object; - _cow_object->cache_ref(); + _cow_object->CachedTypedWritableReferenceCount::cache_ref(); _cow_object->_lock_status = CopyOnWriteObject::LS_locked_write; _cow_object->_locking_thread = current_thread; + return new_object; + } else if (_cow_object->get_cache_ref_count() > 1) { // No one else has it specifically read-locked, but there are other // CopyOnWritePointers holding the same object, so we should make our own @@ -115,19 +113,17 @@ get_write_pointer() { } PT(CopyOnWriteObject) new_object = _cow_object->make_cow_copy(); + _cow_object->CachedTypedWritableReferenceCount::cache_unref(); + _cow_object->_lock_mutex.release(); - // We can't call cache_unref_delete, because we hold the lock. - if (!_cow_object->CachedTypedWritableReferenceCount::cache_unref()) { - _cow_object->_lock_mutex.release(); - delete _cow_object; - } else { - _cow_object->_lock_mutex.release(); - } + MutexHolder holder(new_object->_lock_mutex); _cow_object = new_object; - _cow_object->cache_ref(); + _cow_object->CachedTypedWritableReferenceCount::cache_ref(); _cow_object->_lock_status = CopyOnWriteObject::LS_locked_write; _cow_object->_locking_thread = current_thread; + return new_object; + } else { // No other thread has the pointer locked, and we're the only // CopyOnWritePointer with this object. We can safely write to it without diff --git a/panda/src/putil/copyOnWritePointer.h b/panda/src/putil/copyOnWritePointer.h index c40c432670..1a7f0e099d 100644 --- a/panda/src/putil/copyOnWritePointer.h +++ b/panda/src/putil/copyOnWritePointer.h @@ -37,8 +37,10 @@ public: INLINE ~CopyOnWritePointer(); #ifdef USE_MOVE_SEMANTICS - INLINE CopyOnWritePointer(CopyOnWritePointer &&move) NOEXCEPT; - INLINE void operator = (CopyOnWritePointer &&move) NOEXCEPT; + INLINE CopyOnWritePointer(CopyOnWritePointer &&from) NOEXCEPT; + INLINE CopyOnWritePointer(PointerTo &&from) NOEXCEPT; + INLINE void operator = (CopyOnWritePointer &&from) NOEXCEPT; + INLINE void operator = (PointerTo &&from) NOEXCEPT; #endif INLINE bool operator == (const CopyOnWritePointer &other) const; @@ -61,7 +63,7 @@ public: INLINE bool test_ref_count_integrity() const; INLINE bool test_ref_count_nonzero() const; -private: +protected: CopyOnWriteObject *_cow_object; }; @@ -84,8 +86,10 @@ public: INLINE void operator = (To *object); #ifdef USE_MOVE_SEMANTICS - INLINE CopyOnWritePointerTo(CopyOnWritePointerTo &&move) NOEXCEPT; - INLINE void operator = (CopyOnWritePointerTo &&move) NOEXCEPT; + INLINE CopyOnWritePointerTo(CopyOnWritePointerTo &&from) NOEXCEPT; + INLINE CopyOnWritePointerTo(PointerTo &&from) NOEXCEPT; + INLINE void operator = (CopyOnWritePointerTo &&from) NOEXCEPT; + INLINE void operator = (PointerTo &&from) NOEXCEPT; #endif #ifdef COW_THREADED From 23645cc407a04034bef457a9a3ab62dc62b94a94 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 13 Dec 2016 21:00:11 +0100 Subject: [PATCH 20/70] Fix DDS load crash with certain formats; support R16, RG16, R32, RG32 --- panda/src/gobj/texture.cxx | 98 ++++++++++++++++++++++++++++++++++++-- panda/src/gobj/texture.h | 2 + 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 76530db95b..115d9529bf 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -3643,13 +3643,13 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) header.pf.four_cc == 0x30315844) { // 'DX10' // A DirectX 10 style texture, which has an additional header. func = read_dds_level_generic_uncompressed; - unsigned int format = dds.get_uint32(); + unsigned int dxgi_format = dds.get_uint32(); unsigned int dimension = dds.get_uint32(); unsigned int misc_flag = dds.get_uint32(); unsigned int array_size = dds.get_uint32(); /*unsigned int alpha_mode = */dds.get_uint32(); - switch (format) { + switch (dxgi_format) { case 2: // DXGI_FORMAT_R32G32B32A32_FLOAT format = F_rgba32; component_type = T_float; @@ -3665,6 +3665,11 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) component_type = T_unsigned_short; func = read_dds_level_abgr16; break; + case 16: // DXGI_FORMAT_R32G32_FLOAT + format = F_rg32; + component_type = T_float; + func = read_dds_level_raw; + break; case 27: // DXGI_FORMAT_R8G8B8A8_TYPELESS case 28: // DXGI_FORMAT_R8G8B8A8_UNORM format = F_rgba8; @@ -3688,6 +3693,41 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) component_type = T_byte; func = read_dds_level_abgr8; break; + case 34: // DXGI_FORMAT_R16G16_FLOAT: + format = F_rg16; + component_type = T_half_float; + func = read_dds_level_raw; + break; + case 35: // DXGI_FORMAT_R16G16_UNORM: + format = F_rg16; + component_type = T_unsigned_short; + func = read_dds_level_raw; + break; + case 37: // DXGI_FORMAT_R16G16_SNORM: + format = F_rg16; + component_type = T_short; + func = read_dds_level_raw; + break; + case 40: // DXGI_FORMAT_D32_FLOAT + format = F_depth_component32; + component_type = T_float; + func = read_dds_level_raw; + break; + case 41: // DXGI_FORMAT_R32_FLOAT + format = F_r32; + component_type = T_float; + func = read_dds_level_raw; + break; + case 42: // DXGI_FORMAT_R32_UINT + format = F_r32i; + component_type = T_unsigned_int; + func = read_dds_level_raw; + break; + case 43: // DXGI_FORMAT_R32_SINT + format = F_r32i; + component_type = T_int; + func = read_dds_level_raw; + break; case 48: // DXGI_FORMAT_R8G8_TYPELESS case 49: // DXGI_FORMAT_R8G8_UNORM format = F_rg; @@ -3703,6 +3743,36 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) format = F_rg8i; component_type = T_byte; break; + case 54: // DXGI_FORMAT_R16_FLOAT: + format = F_r16; + component_type = T_half_float; + func = read_dds_level_raw; + break; + case 55: // DXGI_FORMAT_D16_UNORM: + format = F_depth_component16; + component_type = T_unsigned_short; + func = read_dds_level_raw; + break; + case 56: // DXGI_FORMAT_R16_UNORM: + format = F_r16; + component_type = T_unsigned_short; + func = read_dds_level_raw; + break; + case 57: // DXGI_FORMAT_R16_UINT: + format = F_r16i; + component_type = T_unsigned_short; + func = read_dds_level_raw; + break; + case 58: // DXGI_FORMAT_R16_SNORM: + format = F_r16; + component_type = T_short; + func = read_dds_level_raw; + break; + case 59: // DXGI_FORMAT_R16_SINT: + format = F_r16i; + component_type = T_short; + func = read_dds_level_raw; + break; case 60: // DXGI_FORMAT_R8_TYPELESS case 61: // DXGI_FORMAT_R8_UNORM format = F_red; @@ -3760,7 +3830,6 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) compression = CM_rgtc; func = read_dds_level_bc4; break; - break; case 82: // DXGI_FORMAT_BC5_TYPELESS case 83: // DXGI_FORMAT_BC5_UNORM format = F_rg; @@ -3786,7 +3855,7 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) break; default: gobj_cat.error() - << filename << ": unsupported DXGI format " << format << ".\n"; + << filename << ": unsupported DXGI format " << dxgi_format << ".\n"; return false; } @@ -8264,6 +8333,7 @@ read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header, int n size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n); size_t row_bytes = x_size * 16; + nassertr(row_bytes * y_size == size, PTA_uchar()); PTA_uchar image = PTA_uchar::empty_array(size); for (int y = y_size - 1; y >= 0; --y) { unsigned char *p = image.p() + y * row_bytes; @@ -8280,6 +8350,26 @@ read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header, int n return image; } +/** + * Called by read_dds for a DDS file that needs no transformations applied. + */ +PTA_uchar Texture:: +read_dds_level_raw(Texture *tex, CData *cdata, const DDSHeader &header, int n, istream &in) { + int x_size = tex->do_get_expected_mipmap_x_size(cdata, n); + int y_size = tex->do_get_expected_mipmap_y_size(cdata, n); + + size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n); + size_t row_bytes = x_size * cdata->_num_components * cdata->_component_width; + nassertr(row_bytes * y_size == size, PTA_uchar()); + PTA_uchar image = PTA_uchar::empty_array(size); + for (int y = y_size - 1; y >= 0; --y) { + unsigned char *p = image.p() + y * row_bytes; + in.read((char *)p, row_bytes); + } + + return image; +} + /** * Called by read_dds for a DDS file whose format isn't one we've specifically * optimized. diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index cd05019416..e40ca6f8e5 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -817,6 +817,8 @@ private: int n, istream &in); static PTA_uchar read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header, int n, istream &in); + static PTA_uchar read_dds_level_raw(Texture *tex, CData *cdata, const DDSHeader &header, + int n, istream &in); static PTA_uchar read_dds_level_generic_uncompressed(Texture *tex, CData *cdata, const DDSHeader &header, int n, istream &in); From 34068dc0c1d88a6111eec380df4096422a58867e Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 13 Dec 2016 21:22:17 +0100 Subject: [PATCH 21/70] Implement support for SSBOs --- panda/src/display/graphicsStateGuardian.I | 8 + panda/src/display/graphicsStateGuardian.cxx | 24 ++- panda/src/display/graphicsStateGuardian.h | 8 + panda/src/glstuff/glBufferContext_src.I | 25 +++ panda/src/glstuff/glBufferContext_src.cxx | 49 +++++ panda/src/glstuff/glBufferContext_src.h | 52 +++++ .../glstuff/glGraphicsStateGuardian_src.cxx | 171 +++++++++++++++- .../src/glstuff/glGraphicsStateGuardian_src.h | 14 ++ panda/src/glstuff/glShaderContext_src.cxx | 53 +++++ panda/src/glstuff/glShaderContext_src.h | 12 ++ panda/src/glstuff/glmisc_src.cxx | 1 + panda/src/glstuff/glstuff_src.cxx | 1 + panda/src/glstuff/glstuff_src.h | 1 + panda/src/gobj/p3gobj_composite2.cxx | 1 + panda/src/gobj/preparedGraphicsObjects.I | 7 +- panda/src/gobj/preparedGraphicsObjects.cxx | 165 +++++++++++++++ panda/src/gobj/preparedGraphicsObjects.h | 19 ++ panda/src/gobj/shaderBuffer.I | 63 ++++++ panda/src/gobj/shaderBuffer.cxx | 193 ++++++++++++++++++ panda/src/gobj/shaderBuffer.h | 97 +++++++++ panda/src/gobj/shaderContext.h | 1 + panda/src/gsgbase/graphicsStateGuardianBase.h | 5 + panda/src/pgraph/nodePath.I | 8 + panda/src/pgraph/nodePath.h | 2 + panda/src/pgraph/shaderAttrib.cxx | 29 +++ panda/src/pgraph/shaderAttrib.h | 1 + panda/src/pgraph/shaderInput.I | 12 ++ panda/src/pgraph/shaderInput.h | 7 +- 28 files changed, 1014 insertions(+), 15 deletions(-) create mode 100644 panda/src/glstuff/glBufferContext_src.I create mode 100644 panda/src/glstuff/glBufferContext_src.cxx create mode 100644 panda/src/glstuff/glBufferContext_src.h create mode 100644 panda/src/gobj/shaderBuffer.I create mode 100644 panda/src/gobj/shaderBuffer.cxx create mode 100644 panda/src/gobj/shaderBuffer.h diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index ea3a9b61ac..15f95a19f4 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -62,6 +62,14 @@ release_all_index_buffers() { return _prepared_objects->release_all_index_buffers(); } +/** + * Frees the resources for all index buffers associated with this GSG. + */ +INLINE int GraphicsStateGuardian:: +release_all_shader_buffers() { + return _prepared_objects->release_all_shader_buffers(); +} + /** * Sets the active flag associated with the GraphicsStateGuardian. If the * GraphicsStateGuardian is marked inactive, nothing is rendered. This is not diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index fee041f57a..d5b2f769a0 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -62,12 +62,15 @@ #include #include -PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Vertex buffer switch:Vertex"); -PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Vertex buffer switch:Index"); +PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector("Buffer switch:Vertex"); +PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector("Buffer switch:Index"); +PStatCollector GraphicsStateGuardian::_shader_buffer_switch_pcollector("Buffer switch:Shader"); PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector("Draw:Transfer data:Vertex buffer"); PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector("Draw:Transfer data:Index buffer"); +PStatCollector GraphicsStateGuardian::_load_shader_buffer_pcollector("Draw:Transfer data:Shader buffer"); PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector("Draw:Transfer data:Create Vertex buffer"); PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector("Draw:Transfer data:Create Index buffer"); +PStatCollector GraphicsStateGuardian::_create_shader_buffer_pcollector("Draw:Transfer data:Create Shader buffer"); PStatCollector GraphicsStateGuardian::_load_texture_pcollector("Draw:Transfer data:Texture"); PStatCollector GraphicsStateGuardian::_data_transferred_pcollector("Data transferred"); PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector("Texture manager"); @@ -104,6 +107,7 @@ PStatCollector GraphicsStateGuardian::_prepare_geom_pcollector("Draw:Prepare:Geo PStatCollector GraphicsStateGuardian::_prepare_shader_pcollector("Draw:Prepare:Shader"); PStatCollector GraphicsStateGuardian::_prepare_vertex_buffer_pcollector("Draw:Prepare:Vertex buffer"); PStatCollector GraphicsStateGuardian::_prepare_index_buffer_pcollector("Draw:Prepare:Index buffer"); +PStatCollector GraphicsStateGuardian::_prepare_shader_buffer_pcollector("Draw:Prepare:Shader buffer"); PStatCollector GraphicsStateGuardian::_draw_set_state_transform_pcollector("Draw:Set State:Transform"); PStatCollector GraphicsStateGuardian::_draw_set_state_alpha_test_pcollector("Draw:Set State:Alpha test"); @@ -657,6 +661,22 @@ void GraphicsStateGuardian:: release_index_buffer(IndexBufferContext *) { } +/** + * Prepares the indicated buffer for retained-mode rendering. + */ +BufferContext *GraphicsStateGuardian:: +prepare_shader_buffer(ShaderBuffer *) { + return (BufferContext *)NULL; +} + +/** + * Frees the resources previously allocated via a call to prepare_data(), + * including deleting the BufferContext itself, if necessary. + */ +void GraphicsStateGuardian:: +release_shader_buffer(BufferContext *) { +} + /** * Begins a new occlusion query. After this call, you may call * begin_draw_primitives() and draw_triangles()/draw_whatever() repeatedly. diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index f8c9dabe6b..81643a1f11 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -88,6 +88,7 @@ PUBLISHED: INLINE int release_all_geoms(); INLINE int release_all_vertex_buffers(); INLINE int release_all_index_buffers(); + INLINE int release_all_shader_buffers(); INLINE void set_active(bool active); INLINE bool is_active() const; @@ -307,6 +308,9 @@ public: virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data); virtual void release_index_buffer(IndexBufferContext *ibc); + virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data); + virtual void release_shader_buffer(BufferContext *ibc); + virtual void begin_occlusion_query(); virtual PT(OcclusionQueryContext) end_occlusion_query(); @@ -640,10 +644,13 @@ public: // Statistics static PStatCollector _vertex_buffer_switch_pcollector; static PStatCollector _index_buffer_switch_pcollector; + static PStatCollector _shader_buffer_switch_pcollector; static PStatCollector _load_vertex_buffer_pcollector; static PStatCollector _load_index_buffer_pcollector; + static PStatCollector _load_shader_buffer_pcollector; static PStatCollector _create_vertex_buffer_pcollector; static PStatCollector _create_index_buffer_pcollector; + static PStatCollector _create_shader_buffer_pcollector; static PStatCollector _load_texture_pcollector; static PStatCollector _data_transferred_pcollector; static PStatCollector _texmgrmem_total_pcollector; @@ -680,6 +687,7 @@ public: static PStatCollector _prepare_shader_pcollector; static PStatCollector _prepare_vertex_buffer_pcollector; static PStatCollector _prepare_index_buffer_pcollector; + static PStatCollector _prepare_shader_buffer_pcollector; // A whole slew of collectors to measure the cost of individual state // changes. These are disabled by default. diff --git a/panda/src/glstuff/glBufferContext_src.I b/panda/src/glstuff/glBufferContext_src.I new file mode 100644 index 0000000000..bec8283a18 --- /dev/null +++ b/panda/src/glstuff/glBufferContext_src.I @@ -0,0 +1,25 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file glBufferContext_src.I + * @author rdb + * @date 2016-12-12 + */ + +/** + * + */ +INLINE CLP(BufferContext):: +CLP(BufferContext)(CLP(GraphicsStateGuardian) *glgsg, + PreparedGraphicsObjects *pgo) : + BufferContext(&pgo->_sbuffer_residency), + AdaptiveLruPage(0), + _glgsg(glgsg) +{ + _index = 0; +} diff --git a/panda/src/glstuff/glBufferContext_src.cxx b/panda/src/glstuff/glBufferContext_src.cxx new file mode 100644 index 0000000000..f2e588f945 --- /dev/null +++ b/panda/src/glstuff/glBufferContext_src.cxx @@ -0,0 +1,49 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file glBufferContext_src.cxx + * @author rdb + * @date 2016-12-12 + */ + +TypeHandle CLP(BufferContext)::_type_handle; + +/** + * Evicts the page from the LRU. Called internally when the LRU determines + * that it is full. May also be called externally when necessary to + * explicitly evict the page. + * + * It is legal for this method to either evict the page as requested, do + * nothing (in which case the eviction will be requested again at the next + * epoch), or requeue itself on the tail of the queue (in which case the + * eviction will be requested again much later). + */ +void CLP(BufferContext):: +evict_lru() { + dequeue_lru(); + + // Make sure the buffer is unbound before we delete it. + if (_glgsg->_current_ibuffer_index == _index) { + if (GLCAT.is_debug() && gl_debug_buffers) { + GLCAT.debug() + << "unbinding index buffer\n"; + } + _glgsg->_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + _glgsg->_current_ibuffer_index = 0; + } + + // Free the buffer. + _glgsg->_glDeleteBuffers(1, &_index); + + // We still need a valid index number, though, in case we want to re-load + // the buffer later. + _glgsg->_glGenBuffers(1, &_index); + + update_data_size_bytes(0); + set_resident(false); +} diff --git a/panda/src/glstuff/glBufferContext_src.h b/panda/src/glstuff/glBufferContext_src.h new file mode 100644 index 0000000000..b6c46aab76 --- /dev/null +++ b/panda/src/glstuff/glBufferContext_src.h @@ -0,0 +1,52 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file glBufferContext_src.h + * @author rdb + * @date 2016-12-12 + */ + +#include "pandabase.h" +#include "bufferContext.h" +#include "deletedChain.h" + +/** + * Caches a GeomPrimitive on the GL as a buffer object. + */ +class EXPCL_GL CLP(BufferContext) : public BufferContext, public AdaptiveLruPage { +public: + INLINE CLP(BufferContext)(CLP(GraphicsStateGuardian) *glgsg, + PreparedGraphicsObjects *pgo); + ALLOC_DELETED_CHAIN(CLP(BufferContext)); + + virtual void evict_lru(); + + CLP(GraphicsStateGuardian) *_glgsg; + + // This is the GL "name" of the data object. + GLuint _index; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + BufferContext::init_type(); + register_type(_type_handle, CLASSPREFIX_QUOTED "BufferContext", + BufferContext::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "glBufferContext_src.I" diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 80719c2e69..98c21610c5 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1796,7 +1796,7 @@ reset() { } #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 // Check for uniform buffers. #ifdef OPENGLES if (is_at_least_gl_version(3, 1) || has_extension("GL_ARB_uniform_buffer_object")) { @@ -1810,12 +1810,30 @@ reset() { get_extension_func("glGetActiveUniformBlockiv"); _glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) get_extension_func("glGetActiveUniformBlockName"); - - _glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) - get_extension_func("glBindBufferBase"); } else { _supports_uniform_buffers = false; } + +#ifndef OPENGLES + // Check for SSBOs. + if (is_at_least_gl_version(4, 3) || has_extension("ARB_shader_storage_buffer_object")) { + _supports_shader_buffers = true; + _glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC) + get_extension_func("glGetProgramInterfaceiv"); + _glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC) + get_extension_func("glGetProgramResourceName"); + _glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC) + get_extension_func("glGetProgramResourceiv"); + } else +#endif + { + _supports_shader_buffers = false; + } + + if (_supports_uniform_buffers || _supports_shader_buffers) { + _glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) + get_extension_func("glBindBufferBase"); + } #endif // Check whether we support geometry instancing and instanced vertex @@ -3031,6 +3049,9 @@ reset() { _current_vertex_buffers.clear(); _current_vertex_format.clear(); memset(_vertex_attrib_columns, 0, sizeof(const GeomVertexColumn *) * 32); + + _current_sbuffer_index = 0; + _current_sbuffer_base.clear(); #endif report_my_gl_errors(); @@ -5873,6 +5894,122 @@ setup_primitive(const unsigned char *&client_pointer, return true; } +#ifndef OPENGLES +/** + * Creates a new retained-mode representation of the given data, and returns a + * newly-allocated BufferContext pointer to reference it. It is the + * responsibility of the calling function to later call release_shader_buffer() + * with this same pointer (which will also delete the pointer). + * + * This function should not be called directly to prepare a buffer. Instead, + * call ShaderBuffer::prepare(). + */ +BufferContext *CLP(GraphicsStateGuardian):: +prepare_shader_buffer(ShaderBuffer *data) { + if (_supports_shader_buffers) { + PStatGPUTimer timer(this, _prepare_shader_buffer_pcollector); + + CLP(BufferContext) *gbc = new CLP(BufferContext)(this, _prepared_objects); + _glGenBuffers(1, &gbc->_index); + + if (GLCAT.is_debug() && gl_debug_buffers) { + GLCAT.debug() + << "creating shader buffer " << (int)gbc->_index << ": "<< *data << "\n"; + } + _glBindBuffer(GL_SHADER_STORAGE_BUFFER, gbc->_index); + _current_sbuffer_index = gbc->_index; + + if (_use_object_labels) { + string name = data->get_name(); + _glObjectLabel(GL_SHADER_STORAGE_BUFFER, gbc->_index, name.size(), name.data()); + } + + uint64_t num_bytes = data->get_data_size_bytes(); + if (_supports_buffer_storage) { + _glBufferStorage(GL_SHADER_STORAGE_BUFFER, num_bytes, data->get_initial_data(), 0); + } else { + _glBufferData(GL_SHADER_STORAGE_BUFFER, num_bytes, data->get_initial_data(), get_usage(data->get_usage_hint())); + } + + gbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru); + + report_my_gl_errors(); + return gbc; + } + + return NULL; +} + +/** + * Binds the given shader buffer to the given binding slot. + */ +void CLP(GraphicsStateGuardian):: +apply_shader_buffer(GLuint base, ShaderBuffer *buffer) { + GLuint index = 0; + if (buffer != NULL) { + BufferContext *bc = buffer->prepare_now(get_prepared_objects(), this); + if (bc != NULL) { + CLP(BufferContext) *gbc = DCAST(CLP(BufferContext), bc); + index = gbc->_index; + gbc->set_active(true); + } + } + + if (base >= _current_sbuffer_base.size()) { + _current_sbuffer_base.resize(base + 1, 0); + } + + if (_current_sbuffer_base[base] != index) { + if (GLCAT.is_spam() && gl_debug_buffers) { + GLCAT.spam() + << "binding shader buffer " << (int)index + << " to index " << base << "\n"; + } + _glBindBufferBase(GL_SHADER_STORAGE_BUFFER, base, index); + _current_sbuffer_base[base] = index; + _current_sbuffer_index = index; + + report_my_gl_errors(); + } +} + +/** + * Frees the GL resources previously allocated for the data. This function + * should never be called directly; instead, call Data::release() (or simply + * let the Data destruct). + */ +void CLP(GraphicsStateGuardian):: +release_shader_buffer(BufferContext *bc) { + nassertv(_supports_buffers); + + CLP(BufferContext) *gbc = DCAST(CLP(BufferContext), bc); + + if (GLCAT.is_debug() && gl_debug_buffers) { + GLCAT.debug() + << "deleting shader buffer " << (int)gbc->_index << "\n"; + } + + // Make sure the buffer is unbound before we delete it. Not strictly + // necessary according to the OpenGL spec, but it might help out a flaky + // driver, and we need to keep our internal state consistent anyway. + if (_current_sbuffer_index == gbc->_index) { + if (GLCAT.is_spam() && gl_debug_buffers) { + GLCAT.spam() + << "unbinding shader buffer\n"; + } + _glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + _current_sbuffer_index = 0; + } + + _glDeleteBuffers(1, &gbc->_index); + report_my_gl_errors(); + + gbc->_index = 0; + + delete gbc; +} +#endif + #ifndef OPENGLES /** * Begins a new occlusion query. After this call, you may call @@ -6499,7 +6636,7 @@ do_issue_shade_model() { #ifndef OPENGLES_1 /** - * + * Called when the current ShaderAttrib state has changed. */ void CLP(GraphicsStateGuardian):: do_issue_shader() { @@ -6512,21 +6649,30 @@ do_issue_shader() { shader = _default_shader; nassertv(shader != NULL); } - #endif + if (shader) { - context = shader->prepare_now(get_prepared_objects(), this); + if (_current_shader != shader) { + context = shader->prepare_now(get_prepared_objects(), this); + } else { + context = _current_shader_context; + } } + #ifndef SUPPORT_FIXED_FUNCTION // If it failed, try applying the default shader. if (shader != _default_shader && (context == 0 || !context->valid())) { shader = _default_shader; nassertv(shader != NULL); - context = shader->prepare_now(get_prepared_objects(), this); + if (_current_shader != shader) { + context = shader->prepare_now(get_prepared_objects(), this); + } else { + context = _current_shader_context; + } } #endif - if (context == 0 || (context->valid() == false)) { + if (context == 0 || !context->valid()) { if (_current_shader_context != 0) { _current_shader_context->unbind(); _current_shader = 0; @@ -6538,12 +6684,16 @@ do_issue_shader() { // bind the new one. if (_current_shader_context != NULL && _current_shader->get_language() != shader->get_language()) { + // If it's a different type of shader, make sure to unbind the old. _current_shader_context->unbind(); } context->bind(); _current_shader = shader; - _current_shader_context = context; } + + // Bind the shader storage buffers. + context->update_shader_buffer_bindings(_current_shader_context); + _current_shader_context = context; } #ifndef OPENGLES @@ -10116,6 +10266,7 @@ set_state_and_transform(const RenderState *target, } #endif + // Update all of the state that is bound to the shader program. if (_current_shader_context != NULL) { _current_shader_context->set_state_and_transform(target, transform, _projection_mat); } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 7659ee13e5..85290cd6f2 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -344,6 +344,12 @@ public: const GeomPrimitivePipelineReader *reader, bool force); +#ifndef OPENGLES + virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data); + void apply_shader_buffer(GLuint base, ShaderBuffer *buffer); + virtual void release_shader_buffer(BufferContext *bc); +#endif + #ifndef OPENGLES virtual void begin_occlusion_query(); virtual PT(OcclusionQueryContext) end_occlusion_query(); @@ -685,6 +691,9 @@ protected: bool _use_vertex_attrib_binding; CPT(GeomVertexFormat) _current_vertex_format; const GeomVertexColumn *_vertex_attrib_columns[32]; + + GLuint _current_sbuffer_index; + pvector _current_sbuffer_base; #endif int _active_texture_stage; @@ -811,6 +820,7 @@ public: #ifndef OPENGLES_1 bool _supports_uniform_buffers; + bool _supports_shader_buffers; PFNGLBINDBUFFERBASEPROC _glBindBufferBase; bool _supports_buffer_storage; @@ -995,6 +1005,9 @@ public: PFNGLMAKETEXTUREHANDLENONRESIDENTPROC _glMakeTextureHandleNonResident; PFNGLUNIFORMHANDLEUI64PROC _glUniformHandleui64; PFNGLUNIFORMHANDLEUI64VPROC _glUniformHandleui64v; + PFNGLGETPROGRAMINTERFACEIVPROC _glGetProgramInterfaceiv; + PFNGLGETPROGRAMRESOURCENAMEPROC _glGetProgramResourceName; + PFNGLGETPROGRAMRESOURCEIVPROC _glGetProgramResourceiv; #endif // !OPENGLES GLenum _edge_clamp; @@ -1090,6 +1103,7 @@ private: friend class CLP(VertexBufferContext); friend class CLP(IndexBufferContext); + friend class CLP(BufferContext); friend class CLP(ShaderContext); friend class CLP(CgShaderContext); friend class CLP(GraphicsBuffer); diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 528b98804c..6947a39235 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -324,6 +324,34 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext } } +#ifndef OPENGLES + // Get the used shader storage blocks. + if (_glgsg->_supports_shader_buffers) { + GLint block_count = 0, block_maxlength = 0; + + _glgsg->_glGetProgramInterfaceiv(_glsl_program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &block_count); + _glgsg->_glGetProgramInterfaceiv(_glsl_program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &block_maxlength); + + block_maxlength = max(64, block_maxlength); + char *block_name_cstr = (char *)alloca(block_maxlength); + + for (int i = 0; i < block_count; ++i) { + block_name_cstr[0] = 0; + _glgsg->_glGetProgramResourceName(_glsl_program, GL_SHADER_STORAGE_BLOCK, i, block_maxlength, NULL, block_name_cstr); + + const GLenum props[] = {GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE}; + GLint values[2]; + _glgsg->_glGetProgramResourceiv(_glsl_program, GL_SHADER_STORAGE_BLOCK, i, 2, props, 2, NULL, values); + + StorageBlock block; + block._name = InternalName::make(block_name_cstr); + block._binding_index = values[0]; + block._min_size = values[1]; + _storage_blocks.push_back(block); + } + } +#endif + // Bind the program, so that we can call glUniform1i for the textures. _glgsg->_glUseProgram(_glsl_program); @@ -2659,6 +2687,31 @@ update_shader_texture_bindings(ShaderContext *prev) { _glgsg->report_my_gl_errors(); } +/** + * Updates the shader buffer bindings for this shader. + */ +void CLP(ShaderContext):: +update_shader_buffer_bindings(ShaderContext *prev) { +#ifndef OPENGLES + // Update the shader storage buffer bindings. + const ShaderAttrib *attrib = _glgsg->_target_shader; + + for (size_t i = 0; i < _storage_blocks.size(); ++i) { + StorageBlock &block = _storage_blocks[i]; + + ShaderBuffer *buffer = attrib->get_shader_input_buffer(block._name); +#ifndef NDEBUG + if (buffer->get_data_size_bytes() < block._min_size) { + GLCAT.error() + << "cannot bind " << *buffer << " to shader because it is too small" + " (expected at least " << block._min_size << " bytes)\n"; + } +#endif + _glgsg->apply_shader_buffer(block._binding_index, buffer); + } +#endif +} + /** * This subroutine prints the infolog for a shader. */ diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index 183f068277..e143774ed6 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -55,6 +55,7 @@ public: bool update_shader_vertex_arrays(ShaderContext *prev, bool force); void disable_shader_texture_bindings() OVERRIDE; void update_shader_texture_bindings(ShaderContext *prev) OVERRIDE; + void update_shader_buffer_bindings(ShaderContext *prev) OVERRIDE; INLINE bool uses_standard_vertex_arrays(void); INLINE bool uses_custom_vertex_arrays(void); @@ -87,6 +88,17 @@ private: pmap _glsl_uniform_handles; #endif +#ifndef OPENGLES + struct StorageBlock { + CPT(InternalName) _name; + GLuint _binding_index; + GLint _min_size; + }; + typedef pvector StorageBlocks; + StorageBlocks _storage_blocks; + BitArray _used_storage_bindings; +#endif + struct ImageInput { CPT(InternalName) _name; CLP(TextureContext) *_gtc; diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index 544a5c2c79..fd2bcf7aee 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -331,6 +331,7 @@ void CLP(init_classes)() { CLP(SamplerContext)::init_type(); #endif CLP(VertexBufferContext)::init_type(); + CLP(BufferContext)::init_type(); CLP(GraphicsBuffer)::init_type(); #ifndef OPENGLES diff --git a/panda/src/glstuff/glstuff_src.cxx b/panda/src/glstuff/glstuff_src.cxx index af8bcc1df3..06abef89f4 100644 --- a/panda/src/glstuff/glstuff_src.cxx +++ b/panda/src/glstuff/glstuff_src.cxx @@ -21,6 +21,7 @@ #include "glSamplerContext_src.cxx" #include "glVertexBufferContext_src.cxx" #include "glIndexBufferContext_src.cxx" +#include "glBufferContext_src.cxx" #include "glOcclusionQueryContext_src.cxx" #include "glTimerQueryContext_src.cxx" #include "glLatencyQueryContext_src.cxx" diff --git a/panda/src/glstuff/glstuff_src.h b/panda/src/glstuff/glstuff_src.h index 46edb3ac83..02e3208445 100644 --- a/panda/src/glstuff/glstuff_src.h +++ b/panda/src/glstuff/glstuff_src.h @@ -33,6 +33,7 @@ #include "glSamplerContext_src.h" #include "glVertexBufferContext_src.h" #include "glIndexBufferContext_src.h" +#include "glBufferContext_src.h" #include "glOcclusionQueryContext_src.h" #include "glTimerQueryContext_src.h" #include "glLatencyQueryContext_src.h" diff --git a/panda/src/gobj/p3gobj_composite2.cxx b/panda/src/gobj/p3gobj_composite2.cxx index 81e23e5c07..56704b12b3 100644 --- a/panda/src/gobj/p3gobj_composite2.cxx +++ b/panda/src/gobj/p3gobj_composite2.cxx @@ -5,6 +5,7 @@ #include "samplerContext.cxx" #include "samplerState.cxx" #include "savedContext.cxx" +#include "shaderBuffer.cxx" #include "shaderContext.cxx" #include "shader.cxx" #include "simpleAllocator.cxx" diff --git a/panda/src/gobj/preparedGraphicsObjects.I b/panda/src/gobj/preparedGraphicsObjects.I index a9bd618ab5..6cc6daf914 100644 --- a/panda/src/gobj/preparedGraphicsObjects.I +++ b/panda/src/gobj/preparedGraphicsObjects.I @@ -45,6 +45,7 @@ release_all() { _texture_residency.set_levels(); _vbuffer_residency.set_levels(); _ibuffer_residency.set_levels(); + _sbuffer_residency.set_levels(); } /** @@ -58,7 +59,8 @@ get_num_queued() const { get_num_queued_geoms() + get_num_queued_shaders() + get_num_queued_vertex_buffers() + - get_num_queued_index_buffers()); + get_num_queued_index_buffers() + + get_num_queued_shader_buffers()); } /** @@ -72,7 +74,8 @@ get_num_prepared() const { get_num_prepared_geoms() + get_num_prepared_shaders() + get_num_prepared_vertex_buffers() + - get_num_prepared_index_buffers()); + get_num_prepared_index_buffers() + + get_num_prepared_shader_buffers()); } /** diff --git a/panda/src/gobj/preparedGraphicsObjects.cxx b/panda/src/gobj/preparedGraphicsObjects.cxx index 7b2b5e08a9..5c9ec855e3 100644 --- a/panda/src/gobj/preparedGraphicsObjects.cxx +++ b/panda/src/gobj/preparedGraphicsObjects.cxx @@ -41,6 +41,7 @@ PreparedGraphicsObjects() : _texture_residency(_name, "texture"), _vbuffer_residency(_name, "vbuffer"), _ibuffer_residency(_name, "ibuffer"), + _sbuffer_residency(_name, "sbuffer"), _graphics_memory_lru("graphics_memory_lru", graphics_memory_limit), _sampler_object_lru("sampler_object_lru", sampler_object_limit) { @@ -121,6 +122,16 @@ PreparedGraphicsObjects:: delete ibc; } _released_index_buffers.clear(); + + release_all_shader_buffers(); + Buffers::iterator bci; + for (bci = _released_shader_buffers.begin(); + bci != _released_shader_buffers.end(); + ++bci) { + BufferContext *bc = (BufferContext *)(*bci); + delete bc; + } + _released_shader_buffers.clear(); } /** @@ -167,6 +178,9 @@ show_residency_trackers(ostream &out) const { out << "\nIndex buffers:\n"; _ibuffer_residency.write(out, 2); + + out << "\nShader buffers:\n"; + _sbuffer_residency.write(out, 2); } /** @@ -1195,6 +1209,155 @@ prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) { return ibc; } +/** + * Indicates that a buffer would like to be put on the list to be prepared + * when the GSG is next ready to do this (presumably at the next frame). + */ +void PreparedGraphicsObjects:: +enqueue_shader_buffer(ShaderBuffer *data) { + ReMutexHolder holder(_lock); + + _enqueued_shader_buffers.insert(data); +} + +/** + * Returns true if the index buffer has been queued on this GSG, false + * otherwise. + */ +bool PreparedGraphicsObjects:: +is_shader_buffer_queued(const ShaderBuffer *data) const { + ReMutexHolder holder(_lock); + + EnqueuedShaderBuffers::const_iterator qi = _enqueued_shader_buffers.find((ShaderBuffer *)data); + return (qi != _enqueued_shader_buffers.end()); +} + +/** + * Removes a buffer from the queued list of data arrays to be prepared. + * Normally it is not necessary to call this, unless you change your mind + * about preparing it at the last minute, since the data will automatically be + * dequeued and prepared at the next frame. + * + * The return value is true if the buffer is successfully dequeued, false if + * it had not been queued. + */ +bool PreparedGraphicsObjects:: +dequeue_shader_buffer(ShaderBuffer *data) { + ReMutexHolder holder(_lock); + + EnqueuedShaderBuffers::iterator qi = _enqueued_shader_buffers.find(data); + if (qi != _enqueued_shader_buffers.end()) { + _enqueued_shader_buffers.erase(qi); + return true; + } + return false; +} + +/** + * Returns true if the index buffer has been prepared on this GSG, false + * otherwise. + */ +bool PreparedGraphicsObjects:: +is_shader_buffer_prepared(const ShaderBuffer *data) const { + return data->is_prepared((PreparedGraphicsObjects *)this); +} + +/** + * Indicates that a data context, created by a previous call to + * prepare_shader_buffer(), is no longer needed. The driver resources will not + * be freed until some GSG calls update(), indicating it is at a stage where + * it is ready to release datas--this prevents conflicts from threading or + * multiple GSG's sharing datas (we have no way of knowing which graphics + * context is currently active, or what state it's in, at the time + * release_shader_buffer is called). + */ +void PreparedGraphicsObjects:: +release_shader_buffer(BufferContext *bc) { + ReMutexHolder holder(_lock); + + bool removed = (_prepared_shader_buffers.erase(bc) != 0); + nassertv(removed); + + _released_shader_buffers.insert(bc); +} + +/** + * Releases all datas at once. This will force them to be reloaded into data + * memory for all GSG's that share this object. Returns the number of datas + * released. + */ +int PreparedGraphicsObjects:: +release_all_shader_buffers() { + ReMutexHolder holder(_lock); + + int num_shader_buffers = (int)_prepared_shader_buffers.size() + (int)_enqueued_shader_buffers.size(); + + Buffers::iterator bci; + for (bci = _prepared_shader_buffers.begin(); + bci != _prepared_shader_buffers.end(); + ++bci) { + + BufferContext *bc = (BufferContext *)(*bci); + _released_shader_buffers.insert(bc); + } + + _prepared_shader_buffers.clear(); + _enqueued_shader_buffers.clear(); + + return num_shader_buffers; +} + +/** + * Returns the number of index buffers that have been enqueued to be prepared + * on this GSG. + */ +int PreparedGraphicsObjects:: +get_num_queued_shader_buffers() const { + return _enqueued_shader_buffers.size(); +} + +/** + * Returns the number of index buffers that have already been prepared on this + * GSG. + */ +int PreparedGraphicsObjects:: +get_num_prepared_shader_buffers() const { + return _prepared_shader_buffers.size(); +} + +/** + * Immediately creates a new BufferContext for the indicated data and + * returns it. This assumes that the GraphicsStateGuardian is the currently + * active rendering context and that it is ready to accept new datas. If this + * is not necessarily the case, you should use enqueue_shader_buffer() instead. + * + * Normally, this function is not called directly. Call Data::prepare_now() + * instead. + * + * The BufferContext contains all of the pertinent information needed by + * the GSG to keep track of this one particular data, and will exist as long + * as the data is ready to be rendered. + * + * When either the Data or the PreparedGraphicsObjects object destructs, the + * BufferContext will be deleted. + */ +BufferContext *PreparedGraphicsObjects:: +prepare_shader_buffer_now(ShaderBuffer *data, GraphicsStateGuardianBase *gsg) { + ReMutexHolder holder(_lock); + + // Ask the GSG to create a brand new BufferContext. There might be + // several GSG's sharing the same set of datas; if so, it doesn't matter + // which of them creates the context (since they're all shared anyway). + BufferContext *bc = gsg->prepare_shader_buffer(data); + + if (bc != (BufferContext *)NULL) { + bool prepared = _prepared_shader_buffers.insert(bc).second; + nassertr(prepared, bc); + } + + return bc; +} + /** * This is called by the GraphicsStateGuardian to indicate that it is about to * begin processing of the frame. @@ -1276,6 +1439,7 @@ begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread) { _texture_residency.begin_frame(current_thread); _vbuffer_residency.begin_frame(current_thread); _ibuffer_residency.begin_frame(current_thread); + _sbuffer_residency.begin_frame(current_thread); // Now prepare all the textures, geoms, and buffers awaiting preparation. EnqueuedTextures::iterator qti; @@ -1359,6 +1523,7 @@ end_frame(Thread *current_thread) { _texture_residency.end_frame(current_thread); _vbuffer_residency.end_frame(current_thread); _ibuffer_residency.end_frame(current_thread); + _sbuffer_residency.end_frame(current_thread); } /** diff --git a/panda/src/gobj/preparedGraphicsObjects.h b/panda/src/gobj/preparedGraphicsObjects.h index cc138576de..1dbde2d305 100644 --- a/panda/src/gobj/preparedGraphicsObjects.h +++ b/panda/src/gobj/preparedGraphicsObjects.h @@ -22,6 +22,7 @@ #include "geomVertexArrayData.h" #include "geomPrimitive.h" #include "shader.h" +#include "shaderBuffer.h" #include "pointerTo.h" #include "pStatCollector.h" #include "pset.h" @@ -35,6 +36,7 @@ class GeomContext; class ShaderContext; class VertexBufferContext; class IndexBufferContext; +class BufferContext; class GraphicsStateGuardianBase; /** @@ -142,6 +144,19 @@ PUBLISHED: prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg); + void enqueue_shader_buffer(ShaderBuffer *data); + bool is_shader_buffer_queued(const ShaderBuffer *data) const; + bool dequeue_shader_buffer(ShaderBuffer *data); + bool is_shader_buffer_prepared(const ShaderBuffer *data) const; + void release_shader_buffer(BufferContext *bc); + int release_all_shader_buffers(); + int get_num_queued_shader_buffers() const; + int get_num_prepared_shader_buffers() const; + + BufferContext * + prepare_shader_buffer_now(ShaderBuffer *data, + GraphicsStateGuardianBase *gsg); + public: void begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread); @@ -160,6 +175,7 @@ private: typedef phash_set Buffers; typedef phash_set< PT(GeomVertexArrayData) > EnqueuedVertexBuffers; typedef phash_set< PT(GeomPrimitive) > EnqueuedIndexBuffers; + typedef phash_set< PT(ShaderBuffer) > EnqueuedShaderBuffers; // Sampler states are stored a little bit differently, as they are mapped by // value and can't store the list of prepared samplers. @@ -207,6 +223,8 @@ private: EnqueuedVertexBuffers _enqueued_vertex_buffers; Buffers _prepared_index_buffers, _released_index_buffers; EnqueuedIndexBuffers _enqueued_index_buffers; + Buffers _prepared_shader_buffers, _released_shader_buffers; + EnqueuedShaderBuffers _enqueued_shader_buffers; BufferCache _vertex_buffer_cache; BufferCacheLRU _vertex_buffer_cache_lru; @@ -220,6 +238,7 @@ public: BufferResidencyTracker _texture_residency; BufferResidencyTracker _vbuffer_residency; BufferResidencyTracker _ibuffer_residency; + BufferResidencyTracker _sbuffer_residency; AdaptiveLru _graphics_memory_lru; SimpleLru _sampler_object_lru; diff --git a/panda/src/gobj/shaderBuffer.I b/panda/src/gobj/shaderBuffer.I new file mode 100644 index 0000000000..eb51f42f4e --- /dev/null +++ b/panda/src/gobj/shaderBuffer.I @@ -0,0 +1,63 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file shaderBuffer.I + * @author rdb + * @date 2016-12-12 + */ + +/** + * Creates an uninitialized buffer object with the given size. For now, these + * parameters cannot be modified, but this may change in the future. + */ +INLINE ShaderBuffer:: +ShaderBuffer(const string &name, uint64_t size, UsageHint usage_hint) : + Namable(name), + _data_size_bytes(size), + _usage_hint(usage_hint) { +} + +/** + * Creates a buffer object initialized with the given data. For now, these + * parameters cannot be modified, but this may change in the future. + */ +INLINE ShaderBuffer:: +ShaderBuffer(const string &name, pvector initial_data, UsageHint usage_hint) : + Namable(name), + _data_size_bytes(initial_data.size()), + _usage_hint(usage_hint), + _initial_data(initial_data) { +} + +/** + * Returns the buffer size in bytes. + */ +INLINE uint64_t ShaderBuffer:: +get_data_size_bytes() const { + return _data_size_bytes; +} + +/** + * Returns the buffer usage hint. + */ +INLINE GeomEnums::UsageHint ShaderBuffer:: +get_usage_hint() const { + return _usage_hint; +} + +/** + * Returns a pointer to the initial buffer data, or NULL if not specified. + */ +INLINE const unsigned char *ShaderBuffer:: +get_initial_data() const { + if (_initial_data.empty()) { + return NULL; + } else { + return &_initial_data[0]; + } +} diff --git a/panda/src/gobj/shaderBuffer.cxx b/panda/src/gobj/shaderBuffer.cxx new file mode 100644 index 0000000000..a7cd5f8150 --- /dev/null +++ b/panda/src/gobj/shaderBuffer.cxx @@ -0,0 +1,193 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file shaderBuffer.cxx + * @author rdb + * @date 2016-12-12 + */ + +#include "shaderBuffer.h" +#include "preparedGraphicsObjects.h" + +TypeHandle ShaderBuffer::_type_handle; + +/** + * + */ +void ShaderBuffer:: +output(ostream &out) const { + out << "buffer " << get_name() << ", " << _data_size_bytes << "B, " << _usage_hint; +} + +/** + * Indicates that the data should be enqueued to be prepared in the indicated + * prepared_objects at the beginning of the next frame. This will ensure the + * data is already loaded into the GSG if it is expected to be rendered soon. + * + * Use this function instead of prepare_now() to preload datas from a user + * interface standpoint. + */ +void ShaderBuffer:: +prepare(PreparedGraphicsObjects *prepared_objects) { + prepared_objects->enqueue_shader_buffer(this); +} + +/** + * Returns true if the data has already been prepared or enqueued for + * preparation on the indicated GSG, false otherwise. + */ +bool ShaderBuffer:: +is_prepared(PreparedGraphicsObjects *prepared_objects) const { + if (_contexts == (Contexts *)NULL) { + return false; + } + Contexts::const_iterator ci; + ci = _contexts->find(prepared_objects); + if (ci != _contexts->end()) { + return true; + } + return prepared_objects->is_shader_buffer_queued(this); +} + +/** + * Creates a context for the data on the particular GSG, if it does not + * already exist. Returns the new (or old) BufferContext. This assumes + * that the GraphicsStateGuardian is the currently active rendering context + * and that it is ready to accept new datas. If this is not necessarily the + * case, you should use prepare() instead. + * + * Normally, this is not called directly except by the GraphicsStateGuardian; + * a data does not need to be explicitly prepared by the user before it may be + * rendered. + */ +BufferContext *ShaderBuffer:: +prepare_now(PreparedGraphicsObjects *prepared_objects, + GraphicsStateGuardianBase *gsg) { + if (_contexts == (Contexts *)NULL) { + _contexts = new Contexts; + } + Contexts::const_iterator ci; + ci = _contexts->find(prepared_objects); + if (ci != _contexts->end()) { + return (*ci).second; + } + + BufferContext *vbc = prepared_objects->prepare_shader_buffer_now(this, gsg); + if (vbc != (BufferContext *)NULL) { + (*_contexts)[prepared_objects] = vbc; + } + return vbc; +} + +/** + * Frees the data context only on the indicated object, if it exists there. + * Returns true if it was released, false if it had not been prepared. + */ +bool ShaderBuffer:: +release(PreparedGraphicsObjects *prepared_objects) { + if (_contexts != (Contexts *)NULL) { + Contexts::iterator ci; + ci = _contexts->find(prepared_objects); + if (ci != _contexts->end()) { + BufferContext *vbc = (*ci).second; + prepared_objects->release_shader_buffer(vbc); + return true; + } + } + + // Maybe it wasn't prepared yet, but it's about to be. + return prepared_objects->dequeue_shader_buffer(this); +} + +/** + * Frees the context allocated on all objects for which the data has been + * declared. Returns the number of contexts which have been freed. + */ +int ShaderBuffer:: +release_all() { + int num_freed = 0; + + if (_contexts != (Contexts *)NULL) { + // We have to traverse a copy of the _contexts list, because the + // PreparedGraphicsObjects object will call clear_prepared() in response + // to each release_shader_buffer(), and we don't want to be modifying the + // _contexts list while we're traversing it. + Contexts temp = *_contexts; + num_freed = (int)_contexts->size(); + + Contexts::const_iterator ci; + for (ci = temp.begin(); ci != temp.end(); ++ci) { + PreparedGraphicsObjects *prepared_objects = (*ci).first; + BufferContext *vbc = (*ci).second; + prepared_objects->release_shader_buffer(vbc); + } + + // Now that we've called release_shader_buffer() on every known context, + // the _contexts list should have completely emptied itself. + nassertr(_contexts == NULL, num_freed); + } + + return num_freed; +} + +/** + * Tells the BamReader how to create objects of type ParamValue. + */ +void ShaderBuffer:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +/** + * Writes the contents of this object to the datagram for shipping out to a + * Bam file. + */ +void ShaderBuffer:: +write_datagram(BamWriter *manager, Datagram &dg) { + dg.add_string(get_name()); + dg.add_uint64(_data_size_bytes); + dg.add_uint8(_usage_hint); + dg.add_bool(!_initial_data.empty()); + dg.append_data(_initial_data.data(), _initial_data.size()); +} + +/** + * This function is called by the BamReader's factory when a new object of + * type ParamValue is encountered in the Bam file. It should create the + * ParamValue and extract its information from the file. + */ +TypedWritable *ShaderBuffer:: +make_from_bam(const FactoryParams ¶ms) { + ShaderBuffer *param = new ShaderBuffer; + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + param->fillin(scan, manager); + + return param; +} + +/** + * This internal function is called by make_from_bam to read in all of the + * relevant data from the BamFile for the new ParamValue. + */ +void ShaderBuffer:: +fillin(DatagramIterator &scan, BamReader *manager) { + set_name(scan.get_string()); + _data_size_bytes = scan.get_uint64(); + _usage_hint = (UsageHint)scan.get_uint8(); + + if (scan.get_bool() && _data_size_bytes > 0) { + nassertv_always(_data_size_bytes <= scan.get_remaining_size()); + _initial_data.resize(_data_size_bytes); + scan.extract_bytes(&_initial_data[0], _data_size_bytes); + } else { + _initial_data.clear(); + } +} diff --git a/panda/src/gobj/shaderBuffer.h b/panda/src/gobj/shaderBuffer.h new file mode 100644 index 0000000000..5faa4322ac --- /dev/null +++ b/panda/src/gobj/shaderBuffer.h @@ -0,0 +1,97 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file shaderBuffer.h + * @author rdb + * @date 2016-12-12 + */ + +#ifndef SHADERBUFFER_H +#define SHADERBUFFER_H + +#include "pandabase.h" +#include "namable.h" +#include "geomEnums.h" + +class BufferContext; +class PreparedGraphicsObjects; + +/** + * This is a generic buffer object that lives in graphics memory. + */ +class EXPCL_PANDA_GOBJ ShaderBuffer : public TypedWritableReferenceCount, public Namable, public GeomEnums { +private: + INLINE ShaderBuffer() DEFAULT_CTOR; + +PUBLISHED: + INLINE ShaderBuffer(const string &name, uint64_t size, UsageHint usage_hint); + INLINE ShaderBuffer(const string &name, pvector initial_data, UsageHint usage_hint); + +public: + INLINE uint64_t get_data_size_bytes() const; + INLINE UsageHint get_usage_hint() const; + INLINE const unsigned char *get_initial_data() const; + + virtual void output(ostream &out) const; + +PUBLISHED: + MAKE_PROPERTY(data_size_bytes, get_data_size_bytes); + MAKE_PROPERTY(usage_hint, get_usage_hint); + + void prepare(PreparedGraphicsObjects *prepared_objects); + bool is_prepared(PreparedGraphicsObjects *prepared_objects) const; + + BufferContext *prepare_now(PreparedGraphicsObjects *prepared_objects, + GraphicsStateGuardianBase *gsg); + bool release(PreparedGraphicsObjects *prepared_objects); + int release_all(); + +private: + uint64_t _data_size_bytes; + UsageHint _usage_hint; + pvector _initial_data; + + typedef pmap Contexts; + Contexts *_contexts; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedWritableReferenceCount::init_type(); + Namable::init_type(); + register_type(_type_handle, "ShaderBuffer", + TypedWritableReferenceCount::get_class_type(), + Namable::get_class_type()); + } + +private: + static TypeHandle _type_handle; +}; + +INLINE ostream &operator << (ostream &out, const ShaderBuffer &m) { + m.output(out); + return out; +} + +#include "shaderBuffer.I" + +#endif diff --git a/panda/src/gobj/shaderContext.h b/panda/src/gobj/shaderContext.h index 2b356cef8f..7a5312faa2 100644 --- a/panda/src/gobj/shaderContext.h +++ b/panda/src/gobj/shaderContext.h @@ -42,6 +42,7 @@ public: INLINE virtual bool update_shader_vertex_arrays(ShaderContext *prev, bool force) { return false; }; INLINE virtual void disable_shader_texture_bindings() {}; INLINE virtual void update_shader_texture_bindings(ShaderContext *prev) {}; + INLINE virtual void update_shader_buffer_bindings(ShaderContext *prev) {}; INLINE virtual bool uses_standard_vertex_arrays(void) { return true; }; INLINE virtual bool uses_custom_vertex_arrays(void) { return false; }; diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 90455869ac..c45f36aca0 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -31,6 +31,7 @@ class GraphicsOutputBase; class VertexBufferContext; class IndexBufferContext; +class BufferContext; class GeomContext; class GeomNode; class Geom; @@ -57,6 +58,7 @@ class SamplerContext; class SamplerState; class Shader; class ShaderContext; +class ShaderBuffer; class RenderState; class TransformState; class Material; @@ -162,6 +164,9 @@ public: virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data)=0; virtual void release_index_buffer(IndexBufferContext *ibc)=0; + virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data)=0; + virtual void release_shader_buffer(BufferContext *ibc)=0; + virtual void dispatch_compute(int size_x, int size_y, int size_z)=0; virtual PT(GeomMunger) get_geom_munger(const RenderState *state, diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index 1e9813debc..cfcef09112 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -1253,6 +1253,14 @@ set_shader_input(CPT_InternalName id, Texture *tex, bool read, bool write, int z set_shader_input(new ShaderInput(id, tex, read, write, z, n, priority)); } +/** + * + */ +INLINE void NodePath:: +set_shader_input(CPT_InternalName id, ShaderBuffer *buf, int priority) { + set_shader_input(new ShaderInput(id, buf, priority)); +} + /** * */ diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index a30fc1d40d..1bbe0845cf 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -61,6 +61,7 @@ class GlobPattern; class PreparedGraphicsObjects; class SamplerState; class Shader; +class ShaderBuffer; class ShaderInput; // @@ -632,6 +633,7 @@ PUBLISHED: INLINE void set_shader_input(CPT_InternalName id, Texture *tex, int priority=0); INLINE void set_shader_input(CPT_InternalName id, Texture *tex, const SamplerState &sampler, int priority=0); INLINE void set_shader_input(CPT_InternalName id, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0); + INLINE void set_shader_input(CPT_InternalName id, ShaderBuffer *buf, int priority=0); INLINE void set_shader_input(CPT_InternalName id, const NodePath &np, int priority=0); INLINE void set_shader_input(CPT_InternalName id, const PTA_float &v, int priority=0); INLINE void set_shader_input(CPT_InternalName id, const PTA_double &v, int priority=0); diff --git a/panda/src/pgraph/shaderAttrib.cxx b/panda/src/pgraph/shaderAttrib.cxx index 93ccf45bc2..758d980a50 100644 --- a/panda/src/pgraph/shaderAttrib.cxx +++ b/panda/src/pgraph/shaderAttrib.cxx @@ -25,6 +25,7 @@ #include "datagram.h" #include "datagramIterator.h" #include "nodePath.h" +#include "shaderBuffer.h" TypeHandle ShaderAttrib::_type_handle; int ShaderAttrib::_attrib_slot; @@ -461,6 +462,34 @@ get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const { } } +/** + * Returns the ShaderInput as a ShaderBuffer. Assertion fails if there is + * none, or if it is not a ShaderBuffer. + */ +ShaderBuffer *ShaderAttrib:: +get_shader_input_buffer(const InternalName *id) const { + Inputs::const_iterator i = _inputs.find(id); + if (i == _inputs.end()) { + ostringstream strm; + strm << "Shader input " << id->get_name() << " is not present.\n"; + nassert_raise(strm.str()); + return NULL; + } else { + const ShaderInput *p = (*i).second; + + if (p->get_value_type() == ShaderInput::M_buffer) { + ShaderBuffer *value; + DCAST_INTO_R(value, p->_value, NULL); + return value; + } + + ostringstream strm; + strm << "Shader input " << id->get_name() << " is not a ShaderBuffer.\n"; + nassert_raise(strm.str()); + return NULL; + } +} + /** * Returns the shader object associated with the node. If get_override * returns true, but get_shader returns NULL, that means that this attribute diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index 08676286f5..5a28e929b1 100644 --- a/panda/src/pgraph/shaderAttrib.h +++ b/panda/src/pgraph/shaderAttrib.h @@ -111,6 +111,7 @@ PUBLISHED: Texture *get_shader_input_texture(const InternalName *id, SamplerState *sampler=NULL) const; const Shader::ShaderPtrData *get_shader_input_ptr(const InternalName *id) const; const LMatrix4 &get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const; + ShaderBuffer *get_shader_input_buffer(const InternalName *id) const; static void register_with_read_factory(); diff --git a/panda/src/pgraph/shaderInput.I b/panda/src/pgraph/shaderInput.I index 52f46369ad..7344717e47 100644 --- a/panda/src/pgraph/shaderInput.I +++ b/panda/src/pgraph/shaderInput.I @@ -55,6 +55,18 @@ ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority) : { } +/** + * + */ +INLINE ShaderInput:: +ShaderInput(CPT_InternalName name, ShaderBuffer *buf, int priority) : + _name(MOVE(name)), + _type(M_buffer), + _priority(priority), + _value(buf) +{ +} + /** * */ diff --git a/panda/src/pgraph/shaderInput.h b/panda/src/pgraph/shaderInput.h index 260d5a6ab1..c91c790618 100644 --- a/panda/src/pgraph/shaderInput.h +++ b/panda/src/pgraph/shaderInput.h @@ -31,6 +31,7 @@ #include "samplerState.h" #include "shader.h" #include "texture.h" +#include "shaderBuffer.h" /** * This is a small container class that can hold any one of the value types @@ -52,6 +53,7 @@ PUBLISHED: INLINE ShaderInput(CPT_InternalName name, int priority=0); INLINE ShaderInput(CPT_InternalName name, Texture *tex, int priority=0); INLINE ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority=0); + INLINE ShaderInput(CPT_InternalName name, ShaderBuffer *buf, int priority=0); INLINE ShaderInput(CPT_InternalName name, const PTA_float &ptr, int priority=0); INLINE ShaderInput(CPT_InternalName name, const PTA_LVecBase4f &ptr, int priority=0); INLINE ShaderInput(CPT_InternalName name, const PTA_LVecBase3f &ptr, int priority=0); @@ -96,7 +98,8 @@ PUBLISHED: M_numeric, M_texture_sampler, M_param, - M_texture_image + M_texture_image, + M_buffer, }; INLINE const InternalName *get_name() const; @@ -123,6 +126,8 @@ private: int _priority; int _type; + friend class ShaderAttrib; + public: static TypeHandle get_class_type() { return _type_handle; From b6cb9b004506cb3d00db22fd276d288c2eabbf8a Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 17 Dec 2016 00:17:30 +0100 Subject: [PATCH 22/70] ffmpeg: support videos with alpha; add ffmpeg-prefer-libvpx prc var ffmpeg-prefer-libvpx forces ffmpeg to use the libvpx decoder for VP8/VP9 files, allowing the playback of WebM files with an alpha channel. --- panda/src/ffmpeg/config_ffmpeg.cxx | 8 ++++ panda/src/ffmpeg/config_ffmpeg.h | 1 + panda/src/ffmpeg/ffmpegVideoCursor.cxx | 61 ++++++++++++++++++-------- panda/src/ffmpeg/ffmpegVideoCursor.h | 1 + 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/panda/src/ffmpeg/config_ffmpeg.cxx b/panda/src/ffmpeg/config_ffmpeg.cxx index 115b3c31c3..f0d6a5518e 100644 --- a/panda/src/ffmpeg/config_ffmpeg.cxx +++ b/panda/src/ffmpeg/config_ffmpeg.cxx @@ -76,6 +76,14 @@ ConfigVariableInt ffmpeg_read_buffer_size "This is important for performance. A typical size is that of a " "cache page, e.g. 4kb.")); +ConfigVariableBool ffmpeg_prefer_libvpx +("ffmpeg-prefer-libvpx", false, + PRC_DESC("If this is true, Panda will overrule ffmpeg's best judgment on " + "which decoder to use for decoding VP8 and VP9 files, and try to " + "choose libvpx. This is useful when you want to play WebM videos " + "with an alpha channel, which aren't supported by ffmpeg's own " + "VP8/VP9 decoders.")); + /** * Initializes the library. This must be called at least once before any of * the functions or classes in this library can be used. Normally it will be diff --git a/panda/src/ffmpeg/config_ffmpeg.h b/panda/src/ffmpeg/config_ffmpeg.h index 58f81af821..c3854fc9e1 100644 --- a/panda/src/ffmpeg/config_ffmpeg.h +++ b/panda/src/ffmpeg/config_ffmpeg.h @@ -31,6 +31,7 @@ extern ConfigVariableBool ffmpeg_support_seek; extern ConfigVariableBool ffmpeg_global_lock; extern ConfigVariableEnum ffmpeg_thread_priority; extern ConfigVariableInt ffmpeg_read_buffer_size; +extern ConfigVariableBool ffmpeg_prefer_libvpx; extern EXPCL_FFMPEG void init_libffmpeg(); diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index 8affe3c116..1829e003de 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -22,6 +22,7 @@ extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" + #include "libavutil/pixdesc.h" #ifdef HAVE_SWSCALE #include "libswscale/swscale.h" #endif @@ -35,11 +36,16 @@ PStatCollector FfmpegVideoCursor::_fetch_buffer_pcollector("*:FFMPEG Video Decod PStatCollector FfmpegVideoCursor::_seek_pcollector("*:FFMPEG Video Decoding:Seek"); PStatCollector FfmpegVideoCursor::_export_frame_pcollector("*:FFMPEG Convert Video to BGR"); - #if LIBAVFORMAT_VERSION_MAJOR < 53 #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO #endif +#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 74, 100) +#define AV_PIX_FMT_NONE PIX_FMT_NONE +#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24 +#define AV_PIX_FMT_BGRA PIX_FMT_BGRA +#endif + /** * This constructor is only used when reading from a bam file. */ @@ -55,6 +61,7 @@ FfmpegVideoCursor() : _format_ctx(NULL), _video_ctx(NULL), _convert_ctx(NULL), + _pixel_format(AV_PIX_FMT_NONE), _video_index(-1), _frame(NULL), _frame_out(NULL), @@ -80,17 +87,6 @@ init_from(FfmpegVideo *source) { ReMutexHolder av_holder(_av_lock); -#ifdef HAVE_SWSCALE - nassertv(_convert_ctx == NULL); - _convert_ctx = sws_getContext(_size_x, _size_y, _video_ctx->pix_fmt, -#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51, 74, 100) - _size_x, _size_y, AV_PIX_FMT_BGR24, -#else - _size_x, _size_y, PIX_FMT_BGR24, -#endif - SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL); -#endif // HAVE_SWSCALE - #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100) _frame = av_frame_alloc(); _frame_out = av_frame_alloc(); @@ -115,6 +111,25 @@ init_from(FfmpegVideo *source) { _eof_known = false; _eof_frame = 0; + // Check if we got an alpha format. Please note that some video codecs + // (eg. libvpx) change the pix_fmt after decoding the first frame, which is + // why we didn't do this earlier. + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(_video_ctx->pix_fmt); + if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0) { + _num_components = 4; + _pixel_format = AV_PIX_FMT_BGRA; + } else { + _num_components = 3; + _pixel_format = AV_PIX_FMT_BGR24; + } + +#ifdef HAVE_SWSCALE + nassertv(_convert_ctx == NULL); + _convert_ctx = sws_getContext(_size_x, _size_y, _video_ctx->pix_fmt, + _size_x, _size_y, _pixel_format, + SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL); +#endif // HAVE_SWSCALE + #ifdef HAVE_THREADS set_max_readahead_frames(ffmpeg_max_readahead_frames); #endif // HAVE_THREADS @@ -495,7 +510,17 @@ open_stream() { return false; } - AVCodec *pVideoCodec = avcodec_find_decoder(_video_ctx->codec_id); + AVCodec *pVideoCodec = NULL; + if (ffmpeg_prefer_libvpx) { + if (_video_ctx->codec_id == AV_CODEC_ID_VP9) { + pVideoCodec = avcodec_find_decoder_by_name("libvpx-vp9"); + } else if (_video_ctx->codec_id == AV_CODEC_ID_VP8) { + pVideoCodec = avcodec_find_decoder_by_name("libvpx"); + } + } + if (pVideoCodec == NULL) { + pVideoCodec = avcodec_find_decoder(_video_ctx->codec_id); + } if (pVideoCodec == NULL) { ffmpeg_cat.info() << "Couldn't find codec\n"; @@ -515,7 +540,7 @@ open_stream() { _size_x = _video_ctx->width; _size_y = _video_ctx->height; - _num_components = 3; // Don't know how to implement RGBA movies yet. + _num_components = 3; _length = (double)_format_ctx->duration / (double)AV_TIME_BASE; _can_seek = true; _can_seek_fast = true; @@ -1075,8 +1100,8 @@ export_frame(FfmpegBuffer *buffer) { return; } - _frame_out->data[0] = buffer->_block + ((_size_y - 1) * _size_x * 3); - _frame_out->linesize[0] = _size_x * -3; + _frame_out->data[0] = buffer->_block + ((_size_y - 1) * _size_x * _num_components); + _frame_out->linesize[0] = _size_x * -_num_components; buffer->_begin_frame = _begin_frame; buffer->_end_frame = _end_frame; @@ -1086,7 +1111,7 @@ export_frame(FfmpegBuffer *buffer) { nassertv(_convert_ctx != NULL && _frame != NULL && _frame_out != NULL); sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize); #else - img_convert((AVPicture *)_frame_out, PIX_FMT_BGR24, + img_convert((AVPicture *)_frame_out, _pixel_format, (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y); #endif } else { @@ -1094,7 +1119,7 @@ export_frame(FfmpegBuffer *buffer) { nassertv(_convert_ctx != NULL && _frame != NULL && _frame_out != NULL); sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize); #else - img_convert((AVPicture *)_frame_out, PIX_FMT_BGR24, + img_convert((AVPicture *)_frame_out, _pixel_format, (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y); #endif } diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.h b/panda/src/ffmpeg/ffmpegVideoCursor.h index a44ec57490..199b533f47 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.h +++ b/panda/src/ffmpeg/ffmpegVideoCursor.h @@ -104,6 +104,7 @@ private: int _max_readahead_frames; ThreadPriority _thread_priority; PT(GenericThread) _thread; + AVPixelFormat _pixel_format; // This global Mutex protects calls to avcodec_opencloseetc. static ReMutex _av_lock; From da0d7752c1701f7416a45aaeeeb8bb102a811b70 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 18 Dec 2016 00:08:59 +0100 Subject: [PATCH 23/70] Register .webm extension for videos --- panda/src/grutil/config_grutil.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/grutil/config_grutil.cxx b/panda/src/grutil/config_grutil.cxx index 5564a3719d..94613f4da6 100644 --- a/panda/src/grutil/config_grutil.cxx +++ b/panda/src/grutil/config_grutil.cxx @@ -131,6 +131,6 @@ init_libgrutil() { MovieTexture::register_with_read_factory(); TexturePool *ts = TexturePool::get_global_ptr(); - ts->register_texture_type(MovieTexture::make_texture, "avi m2v mov mpg mpeg mp4 wmv asf flv nut ogm mkv ogv"); + ts->register_texture_type(MovieTexture::make_texture, "avi m2v mov mpg mpeg mp4 wmv asf flv nut ogm mkv ogv webm"); #endif } From 36f2eda9ecf9a84fbdd8b8a27adb0b757818c223 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 18 Dec 2016 00:12:26 +0100 Subject: [PATCH 24/70] Fix name of "Buffer switch" pcollector in pStatProperties.cxx --- panda/src/pstatclient/pStatProperties.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index ca8c7c8ead..7b14891daa 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -151,9 +151,9 @@ static TimeCollectorProperties time_properties[] = { static LevelCollectorProperties level_properties[] = { { 1, "Graphics memory", { 0.0, 0.0, 1.0 }, "MB", 64, 1048576 }, - { 1, "Vertex buffer switch", { 0.0, 0.6, 0.8 }, "", 500 }, - { 1, "Vertex buffer switch:Vertex", { 0.8, 0.0, 0.6 } }, - { 1, "Vertex buffer switch:Index", { 0.8, 0.6, 0.3 } }, + { 1, "Buffer switch", { 0.0, 0.6, 0.8 }, "", 500 }, + { 1, "Buffer switch:Vertex", { 0.8, 0.0, 0.6 } }, + { 1, "Buffer switch:Index", { 0.8, 0.6, 0.3 } }, { 1, "Geom cache size", { 0.6, 0.8, 0.6 }, "", 500 }, { 1, "Geom cache size:Active", { 0.9, 1.0, 0.3 }, "", 500 }, { 1, "Geom cache operations", { 1.0, 0.6, 0.6 }, "", 500 }, From 4b5c31716036258f421bd783faaac16e7fdf3ccb Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 19 Dec 2016 22:26:16 +0100 Subject: [PATCH 25/70] Improve shader caching; cache result of preprocess if cache-generated-shaders is set --- panda/src/gobj/shader.cxx | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index e067c18582..306f76f6f8 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -2380,6 +2380,12 @@ do_read_source(string &into, const Filename &fn, BamCacheRecord *record) { _last_modified = max(_last_modified, vf->get_timestamp()); _source_files.push_back(vf->get_filename()); } + + // Strip trailing whitespace. + while (isspace(into[into.size() - 1])) { + into.resize(into.size() - 1); + } + return true; } @@ -2521,6 +2527,11 @@ r_preprocess_source(ostream &out, const Filename &fn, line += line2.substr(block_end + 2); } + // Strip trailing whitespace. + while (isspace(line[line.size() - 1])) { + line.resize(line.size() - 1); + } + // Check if this line contains a #directive. char directive[64]; if (line.size() < 8 || sscanf(line.c_str(), " # %63s", directive) != 1) { @@ -2940,6 +2951,14 @@ load(const Filename &file, ShaderLanguage lang) { } _load_table[sfile] = shader; + + if (cache_generated_shaders) { + ShaderTable::const_iterator i = _make_table.find(shader->_text); + if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) { + return i->second; + } + _make_table[shader->_text] = shader; + } return shader; } @@ -2970,6 +2989,14 @@ load(ShaderLanguage lang, const Filename &vertex, } _load_table[sfile] = shader; + + if (cache_generated_shaders) { + ShaderTable::const_iterator i = _make_table.find(shader->_text); + if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) { + return i->second; + } + _make_table[shader->_text] = shader; + } return shader; } @@ -3025,14 +3052,21 @@ load_compute(ShaderLanguage lang, const Filename &fn) { if (!shader->read(sfile, record)) { return NULL; } + _load_table[sfile] = shader; + + if (cache_generated_shaders) { + ShaderTable::const_iterator i = _make_table.find(shader->_text); + if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) { + return i->second; + } + _make_table[shader->_text] = shader; + } // It makes little sense to cache the shader before compilation, so we keep // the record for when we have the compiled the shader. swap(shader->_record, record); shader->_cache_compiled_shader = BamCache::get_global_ptr()->get_cache_compiled_shaders(); shader->_fullpath = shader->_source_files[0]; - - _load_table[sfile] = shader; return shader; } @@ -3166,7 +3200,6 @@ make_compute(ShaderLanguage lang, const string &body) { sbody._separate = true; sbody._compute = body; - if (cache_generated_shaders) { ShaderTable::const_iterator i = _make_table.find(sbody); if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) { From da79c28a6cbbfc4a42914c6826ecc8985f83e9d3 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 19 Dec 2016 23:29:42 +0100 Subject: [PATCH 26/70] Add RectangleLight class --- panda/src/pgraphnodes/config_pgraphnodes.cxx | 3 + .../pgraphnodes/p3pgraphnodes_composite2.cxx | 1 + panda/src/pgraphnodes/rectangleLight.I | 59 +++++++ panda/src/pgraphnodes/rectangleLight.cxx | 150 ++++++++++++++++++ panda/src/pgraphnodes/rectangleLight.h | 98 ++++++++++++ 5 files changed, 311 insertions(+) create mode 100644 panda/src/pgraphnodes/rectangleLight.I create mode 100644 panda/src/pgraphnodes/rectangleLight.cxx create mode 100644 panda/src/pgraphnodes/rectangleLight.h diff --git a/panda/src/pgraphnodes/config_pgraphnodes.cxx b/panda/src/pgraphnodes/config_pgraphnodes.cxx index 47b0ed3baf..f512110858 100644 --- a/panda/src/pgraphnodes/config_pgraphnodes.cxx +++ b/panda/src/pgraphnodes/config_pgraphnodes.cxx @@ -26,6 +26,7 @@ #include "lodNode.h" #include "nodeCullCallbackData.h" #include "pointLight.h" +#include "rectangleLight.h" #include "selectiveChildNode.h" #include "sequenceNode.h" #include "shaderGenerator.h" @@ -121,6 +122,7 @@ init_libpgraphnodes() { LODNode::init_type(); NodeCullCallbackData::init_type(); PointLight::init_type(); + RectangleLight::init_type(); SelectiveChildNode::init_type(); SequenceNode::init_type(); ShaderGenerator::init_type(); @@ -137,6 +139,7 @@ init_libpgraphnodes() { LightNode::register_with_read_factory(); LODNode::register_with_read_factory(); PointLight::register_with_read_factory(); + RectangleLight::register_with_read_factory(); SelectiveChildNode::register_with_read_factory(); SequenceNode::register_with_read_factory(); SphereLight::register_with_read_factory(); diff --git a/panda/src/pgraphnodes/p3pgraphnodes_composite2.cxx b/panda/src/pgraphnodes/p3pgraphnodes_composite2.cxx index 952a2448c9..4dd4f04bff 100644 --- a/panda/src/pgraphnodes/p3pgraphnodes_composite2.cxx +++ b/panda/src/pgraphnodes/p3pgraphnodes_composite2.cxx @@ -1,5 +1,6 @@ #include "nodeCullCallbackData.cxx" #include "pointLight.cxx" +#include "rectangleLight.cxx" #include "sceneGraphAnalyzer.cxx" #include "selectiveChildNode.cxx" #include "sequenceNode.cxx" diff --git a/panda/src/pgraphnodes/rectangleLight.I b/panda/src/pgraphnodes/rectangleLight.I new file mode 100644 index 0000000000..c97dd536f2 --- /dev/null +++ b/panda/src/pgraphnodes/rectangleLight.I @@ -0,0 +1,59 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file rectangleLight.I + * @author rdb + * @date 2016-12-19 + */ + +/** + * + */ +INLINE RectangleLight::CData:: +CData() : + _max_distance(make_inf((PN_stdfloat)0)) +{ +} + +/** + * + */ +INLINE RectangleLight::CData:: +CData(const RectangleLight::CData ©) : + _max_distance(copy._max_distance) +{ +} + +/** + * Returns the color of specular highlights generated by the light. This is + * usually the same as get_color(). + */ +INLINE const LColor &RectangleLight:: +get_specular_color() const { + return get_color(); +} + +/** + * Returns the maximum distance at which the light has any effect, as previously + * specified by set_max_distance. + */ +INLINE PN_stdfloat RectangleLight:: +get_max_distance() const { + CDReader cdata(_cycler); + return cdata->_max_distance; +} + +/** + * Sets the radius of the light's sphere of influence. Beyond this distance, the + * light may be attenuated to zero, if this is supported by the shader. + */ +INLINE void RectangleLight:: +set_max_distance(PN_stdfloat max_distance) { + CDWriter cdata(_cycler); + cdata->_max_distance = max_distance; +} diff --git a/panda/src/pgraphnodes/rectangleLight.cxx b/panda/src/pgraphnodes/rectangleLight.cxx new file mode 100644 index 0000000000..187d35cd2d --- /dev/null +++ b/panda/src/pgraphnodes/rectangleLight.cxx @@ -0,0 +1,150 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file rectangleLight.cxx + * @author rdb + * @date 2016-12-19 + */ + +#include "rectangleLight.h" +#include "graphicsStateGuardianBase.h" +#include "bamWriter.h" +#include "bamReader.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle RectangleLight::_type_handle; + +/** + * + */ +CycleData *RectangleLight::CData:: +make_copy() const { + return new CData(*this); +} + +/** + * Writes the contents of this object to the datagram for shipping out to a + * Bam file. + */ +void RectangleLight::CData:: +write_datagram(BamWriter *manager, Datagram &dg) const { + dg.add_stdfloat(_max_distance); +} + +/** + * This internal function is called by make_from_bam to read in all of the + * relevant data from the BamFile for the new Light. + */ +void RectangleLight::CData:: +fillin(DatagramIterator &scan, BamReader *manager) { + _max_distance = scan.get_stdfloat(); +} + +/** + * + */ +RectangleLight:: +RectangleLight(const string &name) : + LightLensNode(name) +{ +} + +/** + * Do not call the copy constructor directly; instead, use make_copy() or + * copy_subgraph() to make a copy of a node. + */ +RectangleLight:: +RectangleLight(const RectangleLight ©) : + LightLensNode(copy), + _cycler(copy._cycler) +{ +} + +/** + * Returns a newly-allocated PandaNode that is a shallow copy of this one. It + * will be a different pointer, but its internal data may or may not be shared + * with that of the original PandaNode. No children will be copied. + */ +PandaNode *RectangleLight:: +make_copy() const { + return new RectangleLight(*this); +} + +/** + * + */ +void RectangleLight:: +write(ostream &out, int indent_level) const { + LightLensNode::write(out, indent_level); + indent(out, indent_level) << *this << "\n"; +} + +/** + * Returns the relative priority associated with all lights of this class. + * This priority is used to order lights whose instance priority + * (get_priority()) is the same--the idea is that other things being equal, + * AmbientLights (for instance) are less important than DirectionalLights. + */ +int RectangleLight:: +get_class_priority() const { + return (int)CP_area_priority; +} + +/** + * + */ +void RectangleLight:: +bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) { +} + +/** + * Tells the BamReader how to create objects of type RectangleLight. + */ +void RectangleLight:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +/** + * Writes the contents of this object to the datagram for shipping out to a + * Bam file. + */ +void RectangleLight:: +write_datagram(BamWriter *manager, Datagram &dg) { + LightLensNode::write_datagram(manager, dg); + manager->write_cdata(dg, _cycler); +} + +/** + * This function is called by the BamReader's factory when a new object of + * type RectangleLight is encountered in the Bam file. It should create the + * RectangleLight and extract its information from the file. + */ +TypedWritable *RectangleLight:: +make_from_bam(const FactoryParams ¶ms) { + RectangleLight *node = new RectangleLight(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + node->fillin(scan, manager); + + return node; +} + +/** + * This internal function is called by make_from_bam to read in all of the + * relevant data from the BamFile for the new RectangleLight. + */ +void RectangleLight:: +fillin(DatagramIterator &scan, BamReader *manager) { + LightLensNode::fillin(scan, manager); + + manager->read_cdata(scan, _cycler); +} diff --git a/panda/src/pgraphnodes/rectangleLight.h b/panda/src/pgraphnodes/rectangleLight.h new file mode 100644 index 0000000000..00d4d586ea --- /dev/null +++ b/panda/src/pgraphnodes/rectangleLight.h @@ -0,0 +1,98 @@ +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file rectangleLight.h + * @author rdb + * @date 2016-12-19 + */ + +#ifndef RECTANGLELIGHT_H +#define RECTANGLELIGHT_H + +#include "pandabase.h" + +#include "lightLensNode.h" +#include "pointLight.h" + +/** + * This is a type of area light that is an axis aligned rectangle, pointing + * along the Y axis in the positive direction. + */ +class EXPCL_PANDA_PGRAPHNODES RectangleLight : public LightLensNode { +PUBLISHED: + RectangleLight(const string &name); + +protected: + RectangleLight(const RectangleLight ©); + +public: + virtual PandaNode *make_copy() const; + virtual void write(ostream &out, int indent_level) const; + +PUBLISHED: + INLINE const LColor &get_specular_color() const FINAL; + + INLINE PN_stdfloat get_max_distance() const; + INLINE void set_max_distance(PN_stdfloat max_distance); + MAKE_PROPERTY(max_distance, get_max_distance, set_max_distance); + + virtual int get_class_priority() const; + +public: + virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light, + int light_id); + +private: + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA_PGRAPHNODES CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); + virtual TypeHandle get_parent_type() const { + return RectangleLight::get_class_type(); + } + + PN_stdfloat _max_distance; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + LightLensNode::init_type(); + register_type(_type_handle, "RectangleLight", + LightLensNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "rectangleLight.I" + +#endif From 04819719fb0918fdc463c1e86ed94b30b6e5e682 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 19 Dec 2016 23:32:23 +0100 Subject: [PATCH 27/70] Fix erroneous report in installer while installing libs --- makepanda/installer.nsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/makepanda/installer.nsi b/makepanda/installer.nsi index d14cb44da9..d934cc4ee0 100755 --- a/makepanda/installer.nsi +++ b/makepanda/installer.nsi @@ -166,6 +166,10 @@ SectionGroup "Panda3D Libraries" SetOutPath $INSTDIR\models File /r /x CVS "${BUILT}\models\*" + SetDetailsPrint both + DetailPrint "Installing optional components..." + SetDetailsPrint listonly + RMDir /r "$SMPROGRAMS\${TITLE}" CreateDirectory "$SMPROGRAMS\${TITLE}" SectionEnd From b2ccf6c0d2313d794468f7ae04beaddf5d930eb8 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 19 Dec 2016 23:35:05 +0100 Subject: [PATCH 28/70] Add ability to produce .whl file Based on original version by pennomi Closes: #83 --- makepanda/makepanda.py | 21 +- makepanda/makewheel.py | 558 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 577 insertions(+), 2 deletions(-) create mode 100644 makepanda/makewheel.py diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 956e8db52c..f2746881bd 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -39,6 +39,7 @@ import sys COMPILER=0 INSTALLER=0 +WHEEL=0 GENMAN=0 COMPRESSOR="zlib" THREADCOUNT=0 @@ -124,6 +125,7 @@ def usage(problem): print(" --verbose (print out more information)") print(" --runtime (build a runtime build instead of an SDK build)") print(" --installer (build an installer)") + print(" --wheel (build a pip-installable .whl)") print(" --optimize X (optimization level can be 1,2,3,4)") print(" --version X (set the panda version number)") print(" --lzma (use lzma compression when building Windows installer)") @@ -159,13 +161,13 @@ def usage(problem): os._exit(1) def parseopts(args): - global INSTALLER,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION + global INSTALLER,WHEEL,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION global STRDXSDKVERSION, WINDOWS_SDK, MSVC_VERSION, BOOUSEINTELCOMPILER longopts = [ "help","distributor=","verbose","runtime","osxtarget=", - "optimize=","everything","nothing","installer","rtdist","nocolor", + "optimize=","everything","nothing","installer","wheel","rtdist","nocolor", "version=","lzma","no-python","threads=","outputdir=","override=", "static","host=","debversion=","rpmrelease=","p3dsuffix=","rtdist-version=", "directx-sdk=", "windows-sdk=", "msvc-version=", "clean", "use-icl", @@ -188,6 +190,7 @@ def parseopts(args): if (option=="--help"): raise Exception elif (option=="--optimize"): optimize=value elif (option=="--installer"): INSTALLER=1 + elif (option=="--wheel"): WHEEL=1 elif (option=="--verbose"): SetVerbose(True) elif (option=="--distributor"): DISTRIBUTOR=value elif (option=="--rtdist"): RTDIST=1 @@ -416,9 +419,18 @@ if (RUNTIME): if (INSTALLER and RTDIST): exit("Cannot build an installer for the rtdist build!") +if (WHEEL and RUNTIME): + exit("Cannot build a wheel for the runtime build!") + +if (WHEEL and RTDIST): + exit("Cannot build a wheel for the rtdist build!") + if (INSTALLER) and (PkgSkip("PYTHON")) and (not RUNTIME) and GetTarget() == 'windows': exit("Cannot build installer on Windows without python") +if WHEEL and PkgSkip("PYTHON"): + exit("Cannot build wheel without Python") + if (RTDIST) and (PkgSkip("WX") and PkgSkip("FLTK")): exit("Cannot build rtdist without wx or fltk") @@ -7239,6 +7251,11 @@ try: MakeInstallerFreeBSD() else: exit("Do not know how to make an installer for this platform") + + if WHEEL: + ProgressOutput(100.0, "Building wheel") + from makewheel import makewheel + makewheel(VERSION, GetOutputDir()) finally: SaveDependencyCache() diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py new file mode 100644 index 0000000000..81caf24701 --- /dev/null +++ b/makepanda/makewheel.py @@ -0,0 +1,558 @@ +""" +Generates a wheel (.whl) file from the output of makepanda. + +Since the wheel requires special linking, this will only work if compiled with +the `--wheel` parameter. +""" +from __future__ import print_function, unicode_literals +from distutils.util import get_platform as get_dist +import json + +import sys +import os +from os.path import join +import shutil +import zipfile +import hashlib +import tempfile +import subprocess +from sysconfig import get_config_var +from optparse import OptionParser +from makepandacore import ColorText, LocateBinary, ParsePandaVersion, GetExtensionSuffix, SetVerbose, GetVerbose +from base64 import urlsafe_b64encode + + +def get_platform(): + p = get_dist().replace('-', '_').replace('.', '_') + #if "linux" in p: + # print(ColorText("red", "WARNING:") + + # " Linux-specific wheel files are not supported." + # " We will generate this wheel as a generic package instead.") + # return "any" + return p + + +def get_abi_tag(): + if sys.version_info >= (3, 0): + soabi = get_config_var('SOABI') + if soabi and soabi.startswith('cpython-'): + return 'cp' + soabi.split('-')[1] + elif soabi: + return soabi.replace('.', '_').replace('-', '_') + + soabi = 'cp%d%d' % (sys.version_info[:2]) + + debug_flag = get_config_var('Py_DEBUG') + if (debug_flag is None and hasattr(sys, 'gettotalrefcount')) or debug_flag: + soabi += 'd' + + malloc_flag = get_config_var('WITH_PYMALLOC') + if malloc_flag is None or malloc_flag: + soabi += 'm' + + if sys.version_info < (3, 3): + usize = get_config_var('Py_UNICODE_SIZE') + if (usize is None and sys.maxunicode == 0x10ffff) or usize == 4: + soabi += 'u' + + return soabi + + +def is_exe_file(path): + return os.path.isfile(path) and path.lower().endswith('.exe') + + +def is_elf_file(path): + base = os.path.basename(path) + return os.path.isfile(path) and '.' not in base and \ + open(path, 'rb').read(4) == b'\x7FELF' + + +def is_mach_o_file(path): + base = os.path.basename(path) + return os.path.isfile(path) and '.' not in base and \ + open(path, 'rb').read(4) == b'\xCA\xFE\xBA\xBE' + + +if sys.platform in ('win32', 'cygwin'): + is_executable = is_exe_file +elif sys.platform == 'darwin': + is_executable = is_mach_o_file +else: + is_executable = is_elf_file + + +# Other global parameters +PY_VERSION = "cp{}{}".format(sys.version_info.major, sys.version_info.minor) +ABI_TAG = get_abi_tag() +PLATFORM_TAG = get_platform() +EXCLUDE_EXT = [".pyc", ".pyo", ".N", ".prebuilt", ".xcf", ".plist", ".vcproj", ".sln"] + +# Plug-ins to install. +PLUGIN_LIBS = ["pandagl", "pandagles", "pandagles2", "p3ptloader", "p3assimp", "p3ffmpeg", "p3openal_audio", "p3fmod_audio"] + +WHEEL_DATA = """Wheel-Version: 1.0 +Generator: makepanda +Root-Is-Purelib: false +Tag: {}-{}-{} +""" + +METADATA = { + "license": "BSD", + "name": "Panda3D", + "metadata_version": "2.0", + "generator": "makepanda", + "summary": "Panda3D is a game engine, a framework for 3D rendering and " + "game development for Python and C++ programs.", + "extensions": { + "python.details": { + "project_urls": { + "Home": "https://www.panda3d.org/" + }, + "document_names": { + "license": "LICENSE.txt" + }, + "contacts": [ + { + "role": "author", + "email": "etc-panda3d@lists.andrew.cmu.edu", + "name": "Panda3D Team" + } + ] + } + }, + "classifiers": [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: End Users/Desktop", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: C++", + "Programming Language :: Python", + "Topic :: Games/Entertainment", + "Topic :: Multimedia", + "Topic :: Multimedia :: Graphics", + "Topic :: Multimedia :: Graphics :: 3D Rendering" + ] +} + +PANDA3D_TOOLS_INIT = """import os, sys +import panda3d + +if sys.platform in ('win32', 'cygwin'): + path_var = 'PATH' +elif sys.platform == 'darwin': + path_var = 'DYLD_LIBRARY_PATH' +else: + path_var = 'LD_LIBRARY_PATH' + +dir = os.path.dirname(panda3d.__file__) +del panda3d +if not os.environ.get(path_var): + os.environ[path_var] = dir +else: + os.environ[path_var] = dir + os.pathsep + os.environ[path_var] + +del os, sys, path_var, dir + + +def _exec_tool(tool): + import os, sys + from subprocess import Popen + tools_dir = os.path.dirname(__file__) + handle = Popen(sys.argv, executable=os.path.join(tools_dir, tool)) + try: + try: + return handle.wait() + except KeyboardInterrupt: + # Give the program a chance to handle the signal gracefully. + return handle.wait() + except: + handle.kill() + handle.wait() + raise + +# Register all the executables in this directory as global functions. +{0} +""" + + +def parse_dependencies_windows(data): + """ Parses the given output from dumpbin /dependents to determine the list + of dll's this executable file depends on. """ + + lines = data.splitlines() + li = 0 + while li < len(lines): + line = lines[li] + li += 1 + if line.find(' has the following dependencies') != -1: + break + + if li < len(lines): + line = lines[li] + if line.strip() == '': + # Skip a blank line. + li += 1 + + # Now we're finding filenames, until the next blank line. + filenames = [] + while li < len(lines): + line = lines[li] + li += 1 + line = line.strip() + if line == '': + # We're done. + return filenames + filenames.append(line) + + # At least we got some data. + return filenames + + +def parse_dependencies_unix(data): + """ Parses the given output from otool -XL or ldd to determine the list of + libraries this executable file depends on. """ + + lines = data.splitlines() + filenames = [] + for l in lines: + l = l.strip() + if l != "statically linked": + filenames.append(l.split(' ', 1)[0]) + return filenames + + +def scan_dependencies(pathname): + """ Checks the named file for DLL dependencies, and adds any appropriate + dependencies found into pluginDependencies and dependentFiles. """ + + if sys.platform == "darwin": + command = ['otool', '-XL', pathname] + elif sys.platform in ("win32", "cygwin"): + command = ['dumpbin', '/dependents', pathname] + else: + command = ['ldd', pathname] + + output = subprocess.check_output(command, universal_newlines=True) + filenames = None + + if sys.platform in ("win32", "cygwin"): + filenames = parse_dependencies_windows(output) + else: + filenames = parse_dependencies_unix(output) + + if filenames is None: + sys.exit("Unable to determine dependencies from %s" % (pathname)) + + return filenames + + +class WheelFile(object): + def __init__(self, name, version): + self.name = name + self.version = version + + wheel_name = "{}-{}-{}-{}-{}.whl".format( + name, version, PY_VERSION, ABI_TAG, PLATFORM_TAG) + + print("Writing %s" % (wheel_name)) + self.zip_file = zipfile.ZipFile(wheel_name, 'w', zipfile.ZIP_DEFLATED) + self.records = [] + + # Used to locate dependency libraries. + self.lib_path = [] + self.dep_paths = {} + + def consider_add_dependency(self, target_path, dep, search_path=None): + """Considers adding a dependency library. + Returns the target_path if it was added, which may be different from + target_path if it was already added earlier, or None if it wasn't.""" + + if dep in self.dep_paths: + # Already considered this. + return self.dep_paths[dep] + + self.dep_paths[dep] = None + + if dep.lower().startswith("python"): + # Don't include the Python library. + return + + source_path = None + + if search_path is None: + search_path = self.lib_path + + for lib_dir in search_path: + # Ignore static stuff. + path = os.path.join(lib_dir, dep) + if os.path.isfile(path): + source_path = os.path.normpath(path) + break + + if not source_path: + # Couldn't find library in the panda3d lib dir. + #print("Ignoring %s" % (dep)) + return + + self.dep_paths[dep] = target_path + self.write_file(target_path, source_path) + return target_path + + def write_file(self, target_path, source_path): + """Adds the given file to the .whl file.""" + + # If this is a .so file, we should set the rpath appropriately. + temp = None + ext = os.path.splitext(source_path)[1] + if ext in ('.so', '.dylib') or '.so.' in os.path.basename(source_path) or \ + (not ext and is_executable(source_path)): + # Scan and add Unix dependencies. + deps = scan_dependencies(source_path) + for dep in deps: + # Only include dependencies with relative path. Otherwise we + # end up overwriting system files like /lib/ld-linux.so.2! + # Yes, it happened to me. + if '/' not in dep: + target_dep = os.path.dirname(target_path) + '/' + dep + self.consider_add_dependency(target_dep, dep) + + suffix = '' + if '.so' in os.path.basename(source_path): + suffix = '.so' + elif ext == '.dylib': + suffix = '.dylib' + + temp = tempfile.NamedTemporaryFile(suffix=suffix, prefix='whl', delete=False) + temp.write(open(source_path, 'rb').read()) + os.fchmod(temp.fileno(), os.fstat(temp.fileno()).st_mode | 0o111) + temp.close() + + # Fix things like @loader_path/../lib references + if sys.platform == "darwin": + loader_path = [os.path.dirname(source_path)] + for dep in deps: + if '@loader_path' not in dep: + continue + + dep_path = dep.replace('@loader_path', '.') + target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep) + target_dep = self.consider_add_dependency(target_dep, dep_path, loader_path) + if not target_dep: + # It won't be included, so no use adjusting the path. + continue + + new_dep = os.path.join('@loader_path', os.path.relpath(target_dep, os.path.dirname(target_path))) + subprocess.call(["install_name_tool", "-change", dep, new_dep, temp.name]) + else: + subprocess.call(["strip", "-s", temp.name]) + subprocess.call(["patchelf", "--set-rpath", "$ORIGIN", temp.name]) + + source_path = temp.name + + ext = ext.lower() + if ext in ('.dll', '.pyd', '.exe'): + # Scan and add Win32 dependencies. + for dep in scan_dependencies(source_path): + target_dep = os.path.dirname(target_path) + '/' + dep + self.consider_add_dependency(target_dep, dep) + + # Calculate the SHA-256 hash and size. + sha = hashlib.sha256() + fp = open(source_path, 'rb') + size = 0 + data = fp.read(1024 * 1024) + while data: + size += len(data) + sha.update(data) + data = fp.read(1024 * 1024) + fp.close() + + # Save it in PEP-0376 format for writing out later. + digest = str(urlsafe_b64encode(sha.digest())) + digest = digest.rstrip('=') + self.records.append("{},sha256={},{}\n".format(target_path, digest, size)) + + if GetVerbose(): + print("Adding %s from %s" % (target_path, source_path)) + self.zip_file.write(source_path, target_path) + + #if temp: + # os.unlink(temp.name) + + def write_file_data(self, target_path, source_data): + """Adds the given file from a string.""" + + sha = hashlib.sha256() + sha.update(source_data.encode()) + digest = str(urlsafe_b64encode(sha.digest())) + digest = digest.rstrip('=') + self.records.append("{},sha256={},{}\n".format(target_path, digest, len(source_data))) + + if GetVerbose(): + print("Adding %s from data" % target_path) + self.zip_file.writestr(target_path, source_data) + + def write_directory(self, target_dir, source_dir): + """Adds the given directory recursively to the .whl file.""" + + for root, dirs, files in os.walk(source_dir): + for file in files: + if os.path.splitext(file)[1] in EXCLUDE_EXT: + continue + + source_path = os.path.join(root, file) + target_path = os.path.join(target_dir, os.path.relpath(source_path, source_dir)) + target_path = target_path.replace('\\', '/') + self.write_file(target_path, source_path) + + def close(self): + # Write the RECORD file. + record_file = "{}-{}.dist-info/RECORD".format(self.name, self.version) + self.records.append(record_file + ",,\n") + + self.zip_file.writestr(record_file, "".join(self.records)) + self.zip_file.close() + + +def makewheel(version, output_dir): + if sys.platform not in ("win32", "darwin") and not sys.platform.startswith("cygwin"): + if not LocateBinary("patchelf"): + raise Exception("patchelf is required when building a Linux wheel.") + + # Global filepaths + panda3d_dir = join(output_dir, "panda3d") + pandac_dir = join(output_dir, "pandac") + direct_dir = join(output_dir, "direct") + models_dir = join(output_dir, "models") + etc_dir = join(output_dir, "etc") + bin_dir = join(output_dir, "bin") + if sys.platform == "win32": + libs_dir = join(output_dir, "bin") + else: + libs_dir = join(output_dir, "lib") + license_src = "LICENSE" + readme_src = "README.md" + + # Update relevant METADATA entries + METADATA['version'] = version + version_classifiers = [ + "Programming Language :: Python :: {}".format(*sys.version_info), + "Programming Language :: Python :: {}.{}".format(*sys.version_info), + ] + METADATA['classifiers'].extend(version_classifiers) + + # Build out the metadata + details = METADATA["extensions"]["python.details"] + homepage = details["project_urls"]["Home"] + author = details["contacts"][0]["name"] + email = details["contacts"][0]["email"] + metadata = ''.join([ + "Metadata-Version: {metadata_version}\n" \ + "Name: {name}\n" \ + "Version: {version}\n" \ + "Summary: {summary}\n" \ + "License: {license}\n".format(**METADATA), + "Home-page: {}\n".format(homepage), + "Author: {}\n".format(author), + "Author-email: {}\n".format(email), + "Platform: {}\n".format(PLATFORM_TAG), + ] + ["Classifier: {}\n".format(c) for c in METADATA['classifiers']]) + + # Zip it up and name it the right thing + whl = WheelFile('panda3d', version) + whl.lib_path = [libs_dir] + + # Add the trees with Python modules. + whl.write_directory('direct', direct_dir) + + # Write the panda3d tree. We use a custom empty __init__ since the + # default one adds the bin directory to the PATH, which we don't have. + whl.write_file_data('panda3d/__init__.py', '') + + ext_suffix = GetExtensionSuffix() + + for file in os.listdir(panda3d_dir): + if file == '__init__.py': + pass + elif file.endswith(ext_suffix) or file.endswith('.py'): + source_path = os.path.join(panda3d_dir, file) + + if file.endswith('.pyd') and PLATFORM_TAG.startswith('cygwin'): + # Rename it to .dll for cygwin Python to be able to load it. + target_path = 'panda3d/' + os.path.splitext(file)[0] + '.dll' + else: + target_path = 'panda3d/' + file + whl.write_file(target_path, source_path) + + # Add plug-ins. + for lib in PLUGIN_LIBS: + plugin_name = 'lib' + lib + if sys.platform in ('win32', 'cygwin'): + plugin_name += '.dll' + elif sys.platform == 'darwin': + plugin_name += '.dylib' + else: + plugin_name += '.so' + plugin_path = os.path.join(libs_dir, plugin_name) + if os.path.isfile(plugin_path): + whl.write_file('panda3d/' + plugin_name, plugin_path) + + # Add the pandac tree for backward compatibility. + for file in os.listdir(pandac_dir): + if file.endswith('.py'): + whl.write_file('pandac/' + file, os.path.join(pandac_dir, file)) + + # Add a panda3d-tools directory containing the executables. + entry_points = '[console_scripts]\n' + tools_init = '' + for file in os.listdir(bin_dir): + source_path = os.path.join(bin_dir, file) + + if is_executable(source_path): + # Put the .exe files inside the panda3d-tools directory. + whl.write_file('panda3d_tools/' + file, source_path) + + # Tell pip to create a wrapper script. + basename = os.path.splitext(file)[0] + 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) + + whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init)) + + # Add the .data directory, containing additional files. + data_dir = 'panda3d-{}.data'.format(version) + #whl.write_directory(data_dir + '/data/etc', etc_dir) + #whl.write_directory(data_dir + '/data/models', models_dir) + + # Actually, let's not. That seems to install the files to the strangest + # places in the user's filesystem. Let's instead put them in panda3d. + whl.write_directory('panda3d/etc', etc_dir) + whl.write_directory('panda3d/models', models_dir) + + # Add the dist-info directory last. + info_dir = 'panda3d-{}.dist-info'.format(version) + whl.write_file_data(info_dir + '/entry_points.txt', entry_points) + whl.write_file_data(info_dir + '/metadata.json', json.dumps(METADATA, indent=4, separators=(',', ': '))) + whl.write_file_data(info_dir + '/METADATA', metadata) + whl.write_file_data(info_dir + '/WHEEL', WHEEL_DATA.format(PY_VERSION, ABI_TAG, PLATFORM_TAG)) + whl.write_file(info_dir + '/LICENSE.txt', license_src) + whl.write_file(info_dir + '/README.md', readme_src) + whl.write_file_data(info_dir + '/top_level.txt', 'direct\npanda3d\npandac\npanda3d_tools\n') + + whl.close() + + +if __name__ == "__main__": + version = ParsePandaVersion("dtool/PandaVersion.pp") + + parser = OptionParser() + parser.add_option('', '--version', dest = 'version', help = 'Panda3D version number (default: %s)' % (version), default = version) + parser.add_option('', '--outputdir', dest = 'outputdir', help = 'Makepanda\'s output directory (default: built)', default = 'built') + parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False) + (options, args) = parser.parse_args() + + SetVerbose(options.verbose) + makewheel(options.version, options.outputdir) From eab2a1a733dbef60f1a9c2bc1a26b5e42a0e6a3f Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 19 Dec 2016 23:39:50 +0100 Subject: [PATCH 29/70] Add CP_area_priority for area lights --- panda/src/pgraph/light.h | 1 + 1 file changed, 1 insertion(+) diff --git a/panda/src/pgraph/light.h b/panda/src/pgraph/light.h index 05fa4c10f6..eeca3409bd 100644 --- a/panda/src/pgraph/light.h +++ b/panda/src/pgraph/light.h @@ -90,6 +90,7 @@ protected: CP_point_priority, CP_directional_priority, CP_spot_priority, + CP_area_priority, }; private: From 1808ad217cea81b5232cf7be977ee4f375416b6a Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Dec 2016 23:14:58 +0100 Subject: [PATCH 30/70] Fix Python 3 error in particle sample in 1.9 --- direct/src/particles/ParticleEffect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/direct/src/particles/ParticleEffect.py b/direct/src/particles/ParticleEffect.py index 914630f19c..3ccec4b589 100644 --- a/direct/src/particles/ParticleEffect.py +++ b/direct/src/particles/ParticleEffect.py @@ -200,7 +200,7 @@ class ParticleEffect(NodePath): def loadConfig(self, filename): data = vfs.readFile(filename, 1) - data = data.replace('\r', '') + data = data.replace(b'\r', b'') try: exec(data) except: From 637767fec893b43c4e6201a434fa435991ffe543 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Dec 2016 23:15:21 +0100 Subject: [PATCH 31/70] Flush nout before inducing crash in assert-abort --- dtool/src/prc/notify.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dtool/src/prc/notify.cxx b/dtool/src/prc/notify.cxx index ebfd19ac42..9a34869923 100644 --- a/dtool/src/prc/notify.cxx +++ b/dtool/src/prc/notify.cxx @@ -405,6 +405,9 @@ assert_failure(const char *expression, int line, // so we can guarantee it has already been constructed. ALIGN_16BYTE ConfigVariableBool assert_abort("assert-abort", false); if (assert_abort) { + // Make sure the error message has been flushed to the output. + nout.flush(); + #ifdef WIN32 // How to trigger an exception in VC++ that offers to take us into // the debugger? abort() doesn't do it. We used to be able to From 5aa86185723f4858827e62703082c3ece672a303 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Dec 2016 23:18:05 +0100 Subject: [PATCH 32/70] Don't error if passing an oversized matrix array to a mat4[1] shader parameter --- panda/src/pgraph/shaderAttrib.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/panda/src/pgraph/shaderAttrib.cxx b/panda/src/pgraph/shaderAttrib.cxx index ad9b1a6eef..350c97ac84 100644 --- a/panda/src/pgraph/shaderAttrib.cxx +++ b/panda/src/pgraph/shaderAttrib.cxx @@ -501,7 +501,8 @@ get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const { nassertr(!np.is_empty(), LMatrix4::ident_mat()); return np.get_transform()->get_mat(); - } else if (p->get_value_type() == ShaderInput::M_numeric && p->get_ptr()._size == 16) { + } else if (p->get_value_type() == ShaderInput::M_numeric && + p->get_ptr()._size >= 16 && (p->get_ptr()._size & 15) == 0) { const Shader::ShaderPtrData &ptr = p->get_ptr(); switch (ptr._type) { @@ -527,7 +528,7 @@ get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const { } ostringstream strm; - strm << "Shader input " << id->get_name() << " is not a NodePath or LMatrix4.\n"; + strm << "Shader input " << id->get_name() << " is not a NodePath, LMatrix4 or PTA_LMatrix4.\n"; nassert_raise(strm.str()); return LMatrix4::ident_mat(); } From a13fb0e8ca4c6e04e4a7a9937e8a6c88758cef1b Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 21 Dec 2016 17:33:22 +0100 Subject: [PATCH 33/70] Fix compilation issue with older ffmpeg versions --- panda/src/ffmpeg/ffmpegVideoCursor.cxx | 6 +++++- panda/src/ffmpeg/ffmpegVideoCursor.h | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index 1829e003de..77598a3644 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -46,6 +46,10 @@ PStatCollector FfmpegVideoCursor::_export_frame_pcollector("*:FFMPEG Convert Vid #define AV_PIX_FMT_BGRA PIX_FMT_BGRA #endif +#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 32, 100) +#define AV_PIX_FMT_FLAG_ALPHA PIX_FMT_FLAG_ALPHA +#endif + /** * This constructor is only used when reading from a bam file. */ @@ -512,7 +516,7 @@ open_stream() { AVCodec *pVideoCodec = NULL; if (ffmpeg_prefer_libvpx) { - if (_video_ctx->codec_id == AV_CODEC_ID_VP9) { + if ((int)_video_ctx->codec_id == 168) { // AV_CODEC_ID_VP9 pVideoCodec = avcodec_find_decoder_by_name("libvpx-vp9"); } else if (_video_ctx->codec_id == AV_CODEC_ID_VP8) { pVideoCodec = avcodec_find_decoder_by_name("libvpx"); diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.h b/panda/src/ffmpeg/ffmpegVideoCursor.h index 199b533f47..23cfda389b 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.h +++ b/panda/src/ffmpeg/ffmpegVideoCursor.h @@ -104,7 +104,12 @@ private: int _max_readahead_frames; ThreadPriority _thread_priority; PT(GenericThread) _thread; + +#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 74, 100) + PixelFormat _pixel_format; +#else AVPixelFormat _pixel_format; +#endif // This global Mutex protects calls to avcodec_opencloseetc. static ReMutex _av_lock; From 92302942feb5d2eacf4dd8bc9caa7fe4cb4aaf3c Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 21 Dec 2016 17:14:10 +0100 Subject: [PATCH 34/70] Changes to build on ancient Linux distributions (CentOS 5 / manylinux) --- doc/ReleaseNotes | 1 + panda/src/glxdisplay/panda_glxext.h | 1 + panda/src/vision/webcamVideoV4L.cxx | 66 +++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 03d2dcf92a..92a31b7d52 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -50,6 +50,7 @@ This issue fixes several bugs that were still found in 1.9.2. * GLSL: fix error when legacy matrix generator inputs are mat3 * Now tries to preserve refresh rate when switching fullscreen on Windows * Fix back-to-front sorting when gl-coordinate-system is changed +* Now also compiles on older Linux distros (eg. CentOS 5 / manylinux1) ------------------------ RELEASE 1.9.2 ------------------------ diff --git a/panda/src/glxdisplay/panda_glxext.h b/panda/src/glxdisplay/panda_glxext.h index 308e166224..5208302929 100644 --- a/panda/src/glxdisplay/panda_glxext.h +++ b/panda/src/glxdisplay/panda_glxext.h @@ -199,6 +199,7 @@ GLXContext glXCreateContextAttribsARB (X11_Display *dpy, GLXFBConfig config, GLX #ifndef GLX_ARB_get_proc_address #define GLX_ARB_get_proc_address 1 +typedef void (*__GLXextFuncPtr)(void); typedef __GLXextFuncPtr ( *PFNGLXGETPROCADDRESSARBPROC) (const GLubyte *procName); #ifdef GLX_GLXEXT_PROTOTYPES __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *procName); diff --git a/panda/src/vision/webcamVideoV4L.cxx b/panda/src/vision/webcamVideoV4L.cxx index 71cee3d312..dd77c6813e 100644 --- a/panda/src/vision/webcamVideoV4L.cxx +++ b/panda/src/vision/webcamVideoV4L.cxx @@ -23,6 +23,72 @@ #include #include +#ifndef CPPPARSER +#ifndef VIDIOC_ENUM_FRAMESIZES +enum v4l2_frmsizetypes { + V4L2_FRMSIZE_TYPE_DISCRETE = 1, + V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, + V4L2_FRMSIZE_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmsize_discrete { + __u32 width; + __u32 height; +}; + +struct v4l2_frmsize_stepwise { + __u32 min_width; + __u32 max_width; + __u32 step_width; + __u32 min_height; + __u32 max_height; + __u32 step_height; +}; + +struct v4l2_frmsizeenum { + __u32 index; + __u32 pixel_format; + __u32 type; + union { + struct v4l2_frmsize_discrete discrete; + struct v4l2_frmsize_stepwise stepwise; + }; + __u32 reserved[2]; +}; + +#define VIDIOC_ENUM_FRAMESIZES _IOWR('V', 74, struct v4l2_frmsizeenum) +#endif + +#ifndef VIDIOC_ENUM_FRAMEINTERVALS +enum v4l2_frmivaltypes { + V4L2_FRMIVAL_TYPE_DISCRETE = 1, + V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, + V4L2_FRMIVAL_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmival_stepwise { + struct v4l2_fract min; + struct v4l2_fract max; + struct v4l2_fract step; +}; + +struct v4l2_frmivalenum { + __u32 index; + __u32 pixel_format; + __u32 width; + __u32 height; + __u32 type; + union { + struct v4l2_fract discrete; + struct v4l2_frmival_stepwise stepwise; + }; + __u32 reserved[2]; +}; + +#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct v4l2_frmivalenum) +#endif +#endif + TypeHandle WebcamVideoV4L::_type_handle; //////////////////////////////////////////////////////////////////// From c1d6e9316631e33b49e10f29de0089a700c49b43 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 21 Dec 2016 17:41:15 +0100 Subject: [PATCH 35/70] Don't link extension modules with libpython; changes to help w/ building whls This fixes compatibility issues with homebrew Python on Mac OS X. This introduces a --no-directscripts flag to disable building packpanda and eggcacher, which require linking with libpython (which is not available on manylinux). When building a wheel, the packpanda and eggcacher modules can instead be added to console_scripts in the entry_points definition. --- direct/src/directscripts/eggcacher.py | 4 ++++ direct/src/directscripts/packpanda.py | 3 +++ doc/ReleaseNotes | 1 + makepanda/makepanda.py | 15 +++++++++++---- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/direct/src/directscripts/eggcacher.py b/direct/src/directscripts/eggcacher.py index ea2f653876..3d53e4e122 100644 --- a/direct/src/directscripts/eggcacher.py +++ b/direct/src/directscripts/eggcacher.py @@ -88,3 +88,7 @@ class EggCacher: progress += size cacher = EggCacher(sys.argv[1:]) + +# Dummy main function so this can be added to console_scripts. +def main(): + return 0 diff --git a/direct/src/directscripts/packpanda.py b/direct/src/directscripts/packpanda.py index 72e33c3e9b..c27c8c678d 100755 --- a/direct/src/directscripts/packpanda.py +++ b/direct/src/directscripts/packpanda.py @@ -419,3 +419,6 @@ else: if not(os.path.exists("/usr/bin/rpmbuild") or os.path.exists("/usr/bin/dpkg-deb")): exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!") +# Dummy main function so this can be added to console_scripts. +def main(): + return 0 diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 92a31b7d52..4ba7c0930f 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -2,6 +2,7 @@ This issue fixes several bugs that were still found in 1.9.2. +* Fix crash when using homebrew Python on Mac OS X * Fix crash when running in Steam on Linux when using OpenAL * Fix crash using wx/tkinter on Mac as long as want-wx/tk is set * Fix loading models from 'models' package with models/ prefix diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 4adcb96d5e..040fb03e2b 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -74,6 +74,7 @@ STRDXSDKVERSION = 'default' STRMSPLATFORMVERSION = 'default' BOOUSEINTELCOMPILER = False OPENCV_VER_23 = False +DIRECTSCRIPTS = True if "MACOSX_DEPLOYMENT_TARGET" in os.environ: OSXTARGET=os.environ["MACOSX_DEPLOYMENT_TARGET"] @@ -169,7 +170,7 @@ def usage(problem): def parseopts(args): global INSTALLER,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL - global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX + global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,DIRECTSCRIPTS global STRDXSDKVERSION, STRMSPLATFORMVERSION, BOOUSEINTELCOMPILER longopts = [ "help","distributor=","verbose","runtime","osxtarget=", @@ -177,7 +178,7 @@ def parseopts(args): "version=","lzma","no-python","threads=","outputdir=","override=", "static","host=","debversion=","rpmrelease=","p3dsuffix=", "directx-sdk=", "platform-sdk=", "use-icl", "clean", - "universal", "target=", "arch=", "git-commit="] + "universal", "target=", "arch=", "git-commit=", "no-directscripts"] anything = 0 optimize = "" target = None @@ -223,6 +224,7 @@ def parseopts(args): # Backward compatibility, OPENGL was renamed to GL elif (option=="--use-opengl"): PkgEnable("GL") elif (option=="--no-opengl"): PkgDisable("GL") + elif (option=="--no-directscripts"): DIRECTSCRIPTS=False elif (option=="--directx-sdk"): STRDXSDKVERSION = value.strip().lower() if STRDXSDKVERSION == '': @@ -799,7 +801,7 @@ if (COMPILER=="GCC"): if GetTarget() != 'darwin': # CgGL is covered by the Cg framework, and we don't need X11 components on OSX if not PkgSkip("NVIDIACG") and not RUNTIME: - SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h") + SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h", thirdparty_dir = "nvidiacg") if not RUNTIME: SmartPkgEnable("X11", "x11", "X11", ("X11", "X11/Xlib.h")) SmartPkgEnable("XRANDR", "xrandr", "Xrandr", "X11/extensions/Xrandr.h") @@ -1646,6 +1648,11 @@ def CompileLink(dll, obj, opts): if LDFLAGS != "": cmd += " " + LDFLAGS + # Don't link libraries with Python. + if "PYTHON" in opts and GetOrigExt(dll) != ".exe" and not RTDIST: + opts = opts[:] + opts.remove("PYTHON") + for (opt, dir) in LIBDIRECTORIES: if (opt=="ALWAYS") or (opt in opts): cmd += ' -L' + BracketNameWithQuotes(dir) @@ -4822,7 +4829,7 @@ if (PkgSkip("DIRECT")==0): OPTS=['DIR:direct/src/directbase', 'PYTHON'] TargetAdd('p3directbase_directbase.obj', opts=OPTS+['BUILDING:DIRECT'], input='directbase.cxx') - if (PkgSkip("PYTHON")==0 and not RTDIST and not RUNTIME): + if (PkgSkip("PYTHON")==0 and not RTDIST and not RUNTIME and DIRECTSCRIPTS): DefSymbol("BUILDING:PACKPANDA", "IMPORT_MODULE", "direct.directscripts.packpanda") TargetAdd('packpanda.obj', opts=OPTS+['BUILDING:PACKPANDA'], input='ppython.cxx') TargetAdd('packpanda.exe', input='packpanda.obj') From 62d0d8292e21561caf6486dfdc3ec87204443f14 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 9 Dec 2016 01:41:32 +0100 Subject: [PATCH 36/70] More texture load/store performance optimisations --- panda/src/gobj/texture.cxx | 53 ++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index bcabaa7a8c..cd5cd54e73 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -6005,10 +6005,11 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, // Most common case: one byte per pixel, and the source image // maxval of 255. No scaling is necessary. Because this is such a common // case, we break it out per component for best performance. + const xel *array = pnmimage.get_array(); switch (num_components) { case 1: for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + const xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); } @@ -6018,9 +6019,10 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, case 2: if (img_has_alpha) { + const xelval *alpha = pnmimage.get_alpha_array(); for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); - xelval *alpha_row = pnmimage.alpha_row(j); + const xel *row = array + j * x_size; + const xelval *alpha_row = alpha + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)alpha_row[i]; @@ -6029,7 +6031,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, } } else { for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + const xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)255; @@ -6041,7 +6043,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, case 3: for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + const xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)PPM_GETG(row[i]); @@ -6053,9 +6055,10 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, case 4: if (img_has_alpha) { + const xelval *alpha = pnmimage.get_alpha_array(); for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); - xelval *alpha_row = pnmimage.alpha_row(j); + const xel *row = array + j * x_size; + const xelval *alpha_row = alpha + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)PPM_GETG(row[i]); @@ -6066,7 +6069,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, } } else { for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + const xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { *p++ = (uchar)PPM_GETB(row[i]); *p++ = (uchar)PPM_GETG(row[i]); @@ -6089,7 +6092,7 @@ convert_from_pnmimage(PTA_uchar &image, size_t page_size, for (int j = y_size-1; j >= 0; j--) { for (int i = 0; i < x_size; i++) { if (is_grayscale) { - store_unscaled_short(p, pnmimage.get_gray_val(i, j)); + store_unscaled_short(p, pnmimage.get_gray_val(i, j)); } else { store_unscaled_short(p, pnmimage.get_blue_val(i, j)); store_unscaled_short(p, pnmimage.get_green_val(i, j)); @@ -6260,11 +6263,13 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, const unsigned char *p = &image[idx]; if (component_width == 1) { + xel *array = pnmimage.get_array(); if (is_grayscale) { if (has_alpha) { + xelval *alpha = pnmimage.get_alpha_array(); for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); - xelval *alpha_row = pnmimage.alpha_row(j); + xel *row = array + j * x_size; + xelval *alpha_row = alpha + j * x_size; for (int i = 0; i < x_size; i++) { PPM_PUTB(row[i], *p++); alpha_row[i] = *p++; @@ -6272,7 +6277,7 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, } } else { for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { PPM_PUTB(row[i], *p++); } @@ -6280,9 +6285,10 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, } } else { if (has_alpha) { + xelval *alpha = pnmimage.get_alpha_array(); for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); - xelval *alpha_row = pnmimage.alpha_row(j); + xel *row = array + j * x_size; + xelval *alpha_row = alpha + j * x_size; for (int i = 0; i < x_size; i++) { PPM_PUTB(row[i], *p++); PPM_PUTG(row[i], *p++); @@ -6292,7 +6298,7 @@ convert_to_pnmimage(PNMImage &pnmimage, int x_size, int y_size, } } else { for (int j = y_size-1; j >= 0; j--) { - xel *row = pnmimage.row(j); + xel *row = array + j * x_size; for (int i = 0; i < x_size; i++) { PPM_PUTB(row[i], *p++); PPM_PUTG(row[i], *p++); @@ -7028,13 +7034,20 @@ compare_images(const PNMImage &a, const PNMImage &b) { nassertr(a.get_x_size() == b.get_x_size() && a.get_y_size() == b.get_y_size(), false); + const xel *a_array = a.get_array(); + const xel *b_array = b.get_array(); + const xelval *a_alpha = a.get_alpha_array(); + const xelval *b_alpha = b.get_alpha_array(); + + int x_size = a.get_x_size(); + int delta = 0; for (int yi = 0; yi < a.get_y_size(); ++yi) { - xel *a_row = a.row(yi); - xel *b_row = b.row(yi); - xelval *a_alpha_row = a.alpha_row(yi); - xelval *b_alpha_row = b.alpha_row(yi); - for (int xi = 0; xi < a.get_x_size(); ++xi) { + const xel *a_row = a_array + yi * x_size; + const xel *b_row = b_array + yi * x_size; + const xelval *a_alpha_row = a_alpha + yi * x_size; + const xelval *b_alpha_row = b_alpha + yi * x_size; + for (int xi = 0; xi < x_size; ++xi) { delta += abs(PPM_GETR(a_row[xi]) - PPM_GETR(b_row[xi])); delta += abs(PPM_GETG(a_row[xi]) - PPM_GETG(b_row[xi])); delta += abs(PPM_GETB(a_row[xi]) - PPM_GETB(b_row[xi])); From e8fbd2f9dac83c7ff1e3085efbd50718714563ab Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 21 Dec 2016 18:14:46 +0100 Subject: [PATCH 37/70] Fix potential crash in shader preprocess code --- panda/src/gobj/shader.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 306f76f6f8..27a055a794 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -2382,7 +2382,7 @@ do_read_source(string &into, const Filename &fn, BamCacheRecord *record) { } // Strip trailing whitespace. - while (isspace(into[into.size() - 1])) { + while (!into.empty() && isspace(into[into.size() - 1])) { into.resize(into.size() - 1); } @@ -2528,7 +2528,7 @@ r_preprocess_source(ostream &out, const Filename &fn, } // Strip trailing whitespace. - while (isspace(line[line.size() - 1])) { + while (!line.empty() && isspace(line[line.size() - 1])) { line.resize(line.size() - 1); } From 7d414500c6578bfbb1b1f489acc2ea7075de5dbb Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 22 Dec 2016 11:32:02 +0100 Subject: [PATCH 38/70] Various compile fixes --- panda/src/ffmpeg/ffmpegVideoCursor.cxx | 15 ++++++++------- panda/src/ffmpeg/ffmpegVideoCursor.h | 6 +----- panda/src/movies/dr_flac.h | 8 ++++++-- .../src/putil/cachedTypedWritableReferenceCount.h | 4 +++- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index 77598a3644..8e2d0b0e47 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -44,10 +44,11 @@ PStatCollector FfmpegVideoCursor::_export_frame_pcollector("*:FFMPEG Convert Vid #define AV_PIX_FMT_NONE PIX_FMT_NONE #define AV_PIX_FMT_BGR24 PIX_FMT_BGR24 #define AV_PIX_FMT_BGRA PIX_FMT_BGRA +typedef PixelFormat AVPixelFormat; #endif #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 32, 100) -#define AV_PIX_FMT_FLAG_ALPHA PIX_FMT_FLAG_ALPHA +#define AV_PIX_FMT_FLAG_ALPHA PIX_FMT_ALPHA #endif /** @@ -65,7 +66,7 @@ FfmpegVideoCursor() : _format_ctx(NULL), _video_ctx(NULL), _convert_ctx(NULL), - _pixel_format(AV_PIX_FMT_NONE), + _pixel_format((int)AV_PIX_FMT_NONE), _video_index(-1), _frame(NULL), _frame_out(NULL), @@ -121,16 +122,16 @@ init_from(FfmpegVideo *source) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(_video_ctx->pix_fmt); if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0) { _num_components = 4; - _pixel_format = AV_PIX_FMT_BGRA; + _pixel_format = (int)AV_PIX_FMT_BGRA; } else { _num_components = 3; - _pixel_format = AV_PIX_FMT_BGR24; + _pixel_format = (int)AV_PIX_FMT_BGR24; } #ifdef HAVE_SWSCALE nassertv(_convert_ctx == NULL); _convert_ctx = sws_getContext(_size_x, _size_y, _video_ctx->pix_fmt, - _size_x, _size_y, _pixel_format, + _size_x, _size_y, (AVPixelFormat)_pixel_format, SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL); #endif // HAVE_SWSCALE @@ -1115,7 +1116,7 @@ export_frame(FfmpegBuffer *buffer) { nassertv(_convert_ctx != NULL && _frame != NULL && _frame_out != NULL); sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize); #else - img_convert((AVPicture *)_frame_out, _pixel_format, + img_convert((AVPicture *)_frame_out, (AVPixelFormat)_pixel_format, (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y); #endif } else { @@ -1123,7 +1124,7 @@ export_frame(FfmpegBuffer *buffer) { nassertv(_convert_ctx != NULL && _frame != NULL && _frame_out != NULL); sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize); #else - img_convert((AVPicture *)_frame_out, _pixel_format, + img_convert((AVPicture *)_frame_out, (AVPixelFormat)_pixel_format, (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y); #endif } diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.h b/panda/src/ffmpeg/ffmpegVideoCursor.h index 23cfda389b..b37637a0b0 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.h +++ b/panda/src/ffmpeg/ffmpegVideoCursor.h @@ -105,11 +105,7 @@ private: ThreadPriority _thread_priority; PT(GenericThread) _thread; -#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 74, 100) - PixelFormat _pixel_format; -#else - AVPixelFormat _pixel_format; -#endif + int _pixel_format; // This global Mutex protects calls to avcodec_opencloseetc. static ReMutex _av_lock; diff --git a/panda/src/movies/dr_flac.h b/panda/src/movies/dr_flac.h index 26d133191d..fdac6a2f79 100644 --- a/panda/src/movies/dr_flac.h +++ b/panda/src/movies/dr_flac.h @@ -534,7 +534,9 @@ static DRFLAC_INLINE uint64_t drflac__swap_endian_uint64(uint64_t n) static DRFLAC_INLINE uint32_t drflac__be2host_32(uint32_t n) { -#ifdef __linux__ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER == __ORDER_LITTLE_ENDIAN__) + return drflac__swap_endian_uint32(n); +#elif defined(__linux__) return be32toh(n); #else if (drflac__is_little_endian()) { @@ -547,7 +549,9 @@ static DRFLAC_INLINE uint32_t drflac__be2host_32(uint32_t n) static DRFLAC_INLINE uint64_t drflac__be2host_64(uint64_t n) { -#ifdef __linux__ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER == __ORDER_LITTLE_ENDIAN__) + return drflac__swap_endian_uint64(n); +#elif defined(__linux__) return be64toh(n); #else if (drflac__is_little_endian()) { diff --git a/panda/src/putil/cachedTypedWritableReferenceCount.h b/panda/src/putil/cachedTypedWritableReferenceCount.h index 7420253fcb..f2e9362dca 100644 --- a/panda/src/putil/cachedTypedWritableReferenceCount.h +++ b/panda/src/putil/cachedTypedWritableReferenceCount.h @@ -46,8 +46,10 @@ PUBLISHED: MAKE_PROPERTY(cache_ref_count, get_cache_ref_count); -protected: +public: INLINE void cache_ref_only() const; + +protected: INLINE void cache_unref_only() const; bool do_test_ref_count_integrity() const; From 056ea94765aeccd659e3905fa46ccc4556eaa9e8 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 22 Dec 2016 21:28:19 +0100 Subject: [PATCH 39/70] Fix PythonThread crash (LP bug 1245818) --- panda/src/pipeline/pythonThread.cxx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/panda/src/pipeline/pythonThread.cxx b/panda/src/pipeline/pythonThread.cxx index c1ef41e344..493b576229 100644 --- a/panda/src/pipeline/pythonThread.cxx +++ b/panda/src/pipeline/pythonThread.cxx @@ -50,6 +50,13 @@ PythonThread(PyObject *function, PyObject *args, nassert_raise("Invalid args passed to PythonThread constructor"); } } + +#ifndef SIMPLE_THREADS + // Ensure that the Python threading system is initialized and ready to go. +#ifdef WITH_THREAD // This symbol defined within Python.h + PyEval_InitThreads(); +#endif +#endif } //////////////////////////////////////////////////////////////////// @@ -59,9 +66,20 @@ PythonThread(PyObject *function, PyObject *args, //////////////////////////////////////////////////////////////////// PythonThread:: ~PythonThread() { + // Unfortunately, we need to grab the GIL to release these things, + // since the destructor could be called from any thread. +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); +#endif + Py_DECREF(_function); Py_XDECREF(_args); Py_XDECREF(_result); + +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + PyGILState_Release(gstate); +#endif } //////////////////////////////////////////////////////////////////// From 601b6b86781912ac761d4d25d1a3499b93b7e690 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 22 Dec 2016 21:29:11 +0100 Subject: [PATCH 40/70] Tweaks for building with static thirdparty libs on Linux Sneak in a function used by makewheel --- makepanda/makepanda.py | 14 +++++++++++--- makepanda/makepandacore.py | 12 ++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 040fb03e2b..cb175542f2 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -561,6 +561,10 @@ if (COMPILER == "MSVC"): LibName(pkg, 'dxerrVNUM.lib'.replace("VNUM", vnum)) #LibName(pkg, 'ddraw.lib') LibName(pkg, 'dxguid.lib') + + if not PkgSkip("FREETYPE") and os.path.isdir(GetThirdpartyDir() + "freetype/include/freetype2"): + IncDirectory("FREETYPE", GetThirdpartyDir() + "freetype/include/freetype2") + IncDirectory("ALWAYS", GetThirdpartyDir() + "extras/include") LibName("WINSOCK", "wsock32.lib") LibName("WINSOCK2", "wsock32.lib") @@ -766,9 +770,13 @@ if (COMPILER=="GCC"): SmartPkgEnable("JPEG", "", ("jpeg"), "jpeglib.h") SmartPkgEnable("PNG", "libpng", ("png"), "png.h", tool = "libpng-config") - if GetTarget() == "darwin" and not PkgSkip("FFMPEG"): - LibName("FFMPEG", "-Wl,-read_only_relocs,suppress") - LibName("FFMPEG", "-framework VideoDecodeAcceleration") + if not PkgSkip("FFMPEG"): + if GetTarget() == "darwin": + LibName("FFMPEG", "-Wl,-read_only_relocs,suppress") + LibName("FFMPEG", "-framework VideoDecodeAcceleration") + elif os.path.isfile(GetThirdpartyDir() + "ffmpeg/lib/libavcodec.a"): + # Needed when linking ffmpeg statically on Linux. + LibName("FFMPEG", "-Wl,-Bsymbolic") cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV") if cv_lib == "opencv_core": diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 1b011188ff..fea93fd434 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -1491,6 +1491,11 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, if os.path.isdir(os.path.join(pkg_dir, "include")): IncDirectory(target_pkg, os.path.join(pkg_dir, "include")) + # Handle cases like freetype2 where the include dir is a subdir under "include" + for i in incs: + if os.path.isdir(os.path.join(pkg_dir, "include", i)): + IncDirectory(target_pkg, os.path.join(pkg_dir, "include", i)) + if os.path.isdir(os.path.join(pkg_dir, "lib")): LibDirectory(target_pkg, os.path.join(pkg_dir, "lib")) @@ -2749,6 +2754,13 @@ def GetOrigExt(x): def SetOrigExt(x, v): ORIG_EXT[x] = v +def GetExtensionSuffix(): + target = GetTarget() + if target == 'windows': + return '.pyd' + else: + return '.so' + def CalcLocation(fn, ipath): if (fn.count("/")): return fn dllext = "" From 2ac1734566dbe5174a72b878a429b581421461ad Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 23 Dec 2016 00:36:59 +0100 Subject: [PATCH 41/70] Fix crash when trying to write 16-bit TIFF file (LP bug 1222922) Note: does not actually add support for writing 16-bit tifs; Panda just doesn't crash but automatically downsamples to 8-bit. --- doc/ReleaseNotes | 1 + panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 4ba7c0930f..3ad0ecd49b 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -76,6 +76,7 @@ remained in the 1.9.1 release, including: * Fix constant reloading of texture when gl-ignore-mipmaps is set * BamReader now releases the GIL (so it can be used threaded) * Fix AttributeError in direct.stdpy.threading module +* Fix crash when writing 16-bit .tif file (now silently downsamples) ------------------------ RELEASE 1.9.1 ------------------------ diff --git a/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx b/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx index ab09b1f034..5bfb87e5c3 100644 --- a/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx +++ b/panda/src/pnmimagetypes/pnmFileTypeTIFF.cxx @@ -1114,13 +1114,13 @@ write_data(xel *array, xelval *alpha) { bytesperrow = _x_size * samplesperpixel; } else if ( grayscale ) { samplesperpixel = 1; - bitspersample = pm_maxvaltobits( _maxval ); + bitspersample = min(8, pm_maxvaltobits(_maxval)); photometric = PHOTOMETRIC_MINISBLACK; i = 8 / bitspersample; bytesperrow = ( _x_size + i - 1 ) / i; } else { samplesperpixel = 1; - bitspersample = 8; + bitspersample = min(8, pm_maxvaltobits(_maxval)); photometric = PHOTOMETRIC_PALETTE; bytesperrow = _x_size; } From 122d9dd3ffa48f4f9297b9b05cb36f9ebcf7b7e6 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 24 Dec 2016 22:19:51 +0100 Subject: [PATCH 42/70] Support building with OpenSSL 1.1.0 --- dtool/src/prc/encryptStreamBuf.cxx | 88 ++++++++++++++++++----------- dtool/src/prc/encryptStreamBuf.h | 6 +- panda/src/downloader/httpClient.cxx | 18 +++--- 3 files changed, 67 insertions(+), 45 deletions(-) diff --git a/dtool/src/prc/encryptStreamBuf.cxx b/dtool/src/prc/encryptStreamBuf.cxx index acf76f9c0a..fed8b8e7b6 100644 --- a/dtool/src/prc/encryptStreamBuf.cxx +++ b/dtool/src/prc/encryptStreamBuf.cxx @@ -73,8 +73,8 @@ EncryptStreamBuf() { _key_length = encryption_key_length; _iteration_count = encryption_iteration_count; - _read_valid = false; - _write_valid = false; + _read_ctx = NULL; + _write_ctx = NULL; _read_overflow_buffer = NULL; _in_read_overflow_buffer = 0; @@ -110,7 +110,6 @@ open_read(istream *source, bool owns_source, const string &password) { _source = source; _owns_source = owns_source; - _read_valid = false; // Now read the header information. StreamReader sr(_source, false); @@ -123,6 +122,11 @@ open_read(istream *source, bool owns_source, const string &password) { if (cipher == NULL) { prc_cat.error() << "Unknown encryption algorithm in stream.\n"; + + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; + } return; } @@ -143,17 +147,25 @@ open_read(istream *source, bool owns_source, const string &password) { string iv = sr.extract_bytes(iv_length); + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_reset(_read_ctx); + } else { + _read_ctx = EVP_CIPHER_CTX_new(); + } + nassertv(_read_ctx != NULL); + // Initialize the context int result; - result = EVP_DecryptInit(&_read_ctx, cipher, NULL, (unsigned char *)iv.data()); + result = EVP_DecryptInit(_read_ctx, cipher, NULL, (unsigned char *)iv.data()); nassertv(result > 0); - result = EVP_CIPHER_CTX_set_key_length(&_read_ctx, key_length); + result = EVP_CIPHER_CTX_set_key_length(_read_ctx, key_length); if (result <= 0) { prc_cat.error() << "Invalid key length " << key_length * 8 << " bits for algorithm " << OBJ_nid2sn(nid) << "\n"; - EVP_CIPHER_CTX_cleanup(&_read_ctx); + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; return; } @@ -167,11 +179,9 @@ open_read(istream *source, bool owns_source, const string &password) { nassertv(result > 0); // Store the key within the context. - result = EVP_DecryptInit(&_read_ctx, NULL, key, NULL); + result = EVP_DecryptInit(_read_ctx, NULL, key, NULL); nassertv(result > 0); - _read_valid = true; - _read_overflow_buffer = new unsigned char[_read_block_size]; _in_read_overflow_buffer = 0; thread_consider_yield(); @@ -182,9 +192,9 @@ open_read(istream *source, bool owns_source, const string &password) { */ void EncryptStreamBuf:: close_read() { - if (_read_valid) { - EVP_CIPHER_CTX_cleanup(&_read_ctx); - _read_valid = false; + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; } if (_read_overflow_buffer != (unsigned char *)NULL) { @@ -211,7 +221,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) { close_write(); _dest = dest; _owns_dest = owns_dest; - _write_valid = false; const EVP_CIPHER *cipher = EVP_get_cipherbyname(_algorithm.c_str()); @@ -219,22 +228,33 @@ open_write(ostream *dest, bool owns_dest, const string &password) { if (cipher == NULL) { prc_cat.error() << "Unknown encryption algorithm: " << _algorithm << "\n"; + + if (_write_ctx != NULL) { + EVP_CIPHER_CTX_free(_write_ctx); + _write_ctx = NULL; + } return; - }; + } int nid = EVP_CIPHER_nid(cipher); int iv_length = EVP_CIPHER_iv_length(cipher); _write_block_size = EVP_CIPHER_block_size(cipher); - unsigned char *iv = (unsigned char *)alloca(iv_length); - // Generate a random IV. It doesn't need to be cryptographically secure, // just unique. + unsigned char *iv = (unsigned char *)alloca(iv_length); RAND_pseudo_bytes(iv, iv_length); + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_reset(_write_ctx); + } else { + _write_ctx = EVP_CIPHER_CTX_new(); + } + nassertv(_write_ctx != NULL); + int result; - result = EVP_EncryptInit(&_write_ctx, cipher, NULL, iv); + result = EVP_EncryptInit(_write_ctx, cipher, NULL, iv); nassertv(result > 0); // Store the appropriate key length in the context. @@ -242,12 +262,13 @@ open_write(ostream *dest, bool owns_dest, const string &password) { if (key_length == 0) { key_length = EVP_CIPHER_key_length(cipher); } - result = EVP_CIPHER_CTX_set_key_length(&_write_ctx, key_length); + result = EVP_CIPHER_CTX_set_key_length(_write_ctx, key_length); if (result <= 0) { prc_cat.error() << "Invalid key length " << key_length * 8 << " bits for algorithm " << OBJ_nid2sn(nid) << "\n"; - EVP_CIPHER_CTX_cleanup(&_write_ctx); + EVP_CIPHER_CTX_free(_write_ctx); + _write_ctx = NULL; return; } @@ -271,7 +292,7 @@ open_write(ostream *dest, bool owns_dest, const string &password) { nassertv(result > 0); // Store the key in the context. - result = EVP_EncryptInit(&_write_ctx, NULL, key, NULL); + result = EVP_EncryptInit(_write_ctx, NULL, key, NULL); nassertv(result > 0); // Now write the header information to the stream. @@ -284,7 +305,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) { sw.add_uint16((uint16_t)count); sw.append_data(iv, iv_length); - _write_valid = true; thread_consider_yield(); } @@ -298,15 +318,16 @@ close_write() { write_chars(pbase(), n); pbump(-(int)n); - if (_write_valid) { + if (_write_ctx != NULL) { unsigned char *write_buffer = (unsigned char *)alloca(_write_block_size); int bytes_written = 0; - EVP_EncryptFinal(&_write_ctx, write_buffer, &bytes_written); + EVP_EncryptFinal(_write_ctx, write_buffer, &bytes_written); thread_consider_yield(); _dest->write((const char *)write_buffer, bytes_written); - _write_valid = false; + EVP_CIPHER_CTX_free(_write_ctx); + _write_ctx = NULL; } if (_owns_dest) { @@ -418,7 +439,7 @@ read_chars(char *start, size_t length) { do { // Get more bytes from the stream. - if (!_read_valid) { + if (_read_ctx == NULL) { return 0; } @@ -429,20 +450,21 @@ read_chars(char *start, size_t length) { int result; if (source_length != 0) { result = - EVP_DecryptUpdate(&_read_ctx, read_buffer, &bytes_read, + EVP_DecryptUpdate(_read_ctx, read_buffer, &bytes_read, source_buffer, source_length); } else { result = - EVP_DecryptFinal(&_read_ctx, read_buffer, &bytes_read); - _read_valid = false; + EVP_DecryptFinal(_read_ctx, read_buffer, &bytes_read); + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; } if (result <= 0) { prc_cat.error() << "Error decrypting stream.\n"; - if (_read_valid) { - EVP_CIPHER_CTX_cleanup(&_read_ctx); - _read_valid = false; + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; } } thread_consider_yield(); @@ -472,13 +494,13 @@ read_chars(char *start, size_t length) { */ void EncryptStreamBuf:: write_chars(const char *start, size_t length) { - if (_write_valid && length != 0) { + if (_write_ctx != NULL && length != 0) { size_t max_write_buffer = length + _write_block_size; unsigned char *write_buffer = (unsigned char *)alloca(max_write_buffer); int bytes_written = 0; int result = - EVP_EncryptUpdate(&_write_ctx, write_buffer, &bytes_written, + EVP_EncryptUpdate(_write_ctx, write_buffer, &bytes_written, (unsigned char *)start, length); if (result <= 0) { prc_cat.error() diff --git a/dtool/src/prc/encryptStreamBuf.h b/dtool/src/prc/encryptStreamBuf.h index 0542457267..4861a89240 100644 --- a/dtool/src/prc/encryptStreamBuf.h +++ b/dtool/src/prc/encryptStreamBuf.h @@ -64,14 +64,12 @@ private: int _key_length; int _iteration_count; - bool _read_valid; - EVP_CIPHER_CTX _read_ctx; + EVP_CIPHER_CTX *_read_ctx; size_t _read_block_size; unsigned char *_read_overflow_buffer; size_t _in_read_overflow_buffer; - bool _write_valid; - EVP_CIPHER_CTX _write_ctx; + EVP_CIPHER_CTX *_write_ctx; size_t _write_block_size; }; diff --git a/panda/src/downloader/httpClient.cxx b/panda/src/downloader/httpClient.cxx index 26baaff0c1..f1ae5d7e7c 100644 --- a/panda/src/downloader/httpClient.cxx +++ b/panda/src/downloader/httpClient.cxx @@ -231,11 +231,7 @@ operator = (const HTTPClient ©) { */ HTTPClient:: ~HTTPClient() { - // Before we can free the context, we must remove the X509_STORE pointer - // from it, so it won't be destroyed along with it (this object is shared - // among all contexts). if (_ssl_ctx != (SSL_CTX *)NULL) { - _ssl_ctx->cert_store = NULL; SSL_CTX_free(_ssl_ctx); } @@ -1122,7 +1118,11 @@ get_ssl_ctx() { OpenSSLWrapper *sslw = OpenSSLWrapper::get_global_ptr(); sslw->notify_ssl_errors(); - SSL_CTX_set_cert_store(_ssl_ctx, sslw->get_x509_store()); + X509_STORE *store = sslw->get_x509_store(); + if (store != NULL) { + X509_STORE_up_ref(store); + } + SSL_CTX_set_cert_store(_ssl_ctx, store); return _ssl_ctx; } @@ -1511,15 +1511,17 @@ x509_name_subset(X509_NAME *name_a, X509_NAME *name_b) { for (int ai = 0; ai < count_a; ai++) { X509_NAME_ENTRY *na = X509_NAME_get_entry(name_a, ai); - int bi = X509_NAME_get_index_by_OBJ(name_b, na->object, -1); + int bi = X509_NAME_get_index_by_OBJ(name_b, X509_NAME_ENTRY_get_object(na), -1); if (bi < 0) { // This entry in name_a is not defined in name_b. return false; } X509_NAME_ENTRY *nb = X509_NAME_get_entry(name_b, bi); - if (na->value->length != nb->value->length || - memcmp(na->value->data, nb->value->data, na->value->length) != 0) { + ASN1_STRING *na_value = X509_NAME_ENTRY_get_data(na); + ASN1_STRING *nb_value = X509_NAME_ENTRY_get_data(nb); + if (na_value->length != nb_value->length || + memcmp(na_value->data, nb_value->data, na_value->length) != 0) { // This entry in name_a doesn't match that of name_b. return false; } From 28bb737597d527ef4184b5f935da7e316a19c2f4 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 24 Dec 2016 22:21:18 +0100 Subject: [PATCH 43/70] Load X11 extensions dynamically; don't expect them to be there at compile time Add x-cursor-size variable for overriding XCursor size. --- makepanda/makepanda.py | 22 +--- panda/src/display/get_x11.h | 13 -- panda/src/x11display/config_x11display.cxx | 5 + panda/src/x11display/config_x11display.h | 1 + panda/src/x11display/x11GraphicsPipe.I | 32 +++++ panda/src/x11display/x11GraphicsPipe.cxx | 140 +++++++++++++++++---- panda/src/x11display/x11GraphicsPipe.h | 56 +++++++++ panda/src/x11display/x11GraphicsWindow.cxx | 140 +++++++++++---------- panda/src/x11display/x11GraphicsWindow.h | 14 +-- 9 files changed, 288 insertions(+), 135 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index f2746881bd..f84beca1bf 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -88,7 +88,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support "MFC", "WX", "FLTK", # Used for web plug-in only "ROCKET", "AWESOMIUM", # GUI libraries "CARBON", "COCOA", # Mac OS X toolkits - "X11", "XF86DGA", "XRANDR", "XCURSOR", # Unix platform support + "X11", # Unix platform support "PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain "SKEL", # Example SKEL project "PANDAFX", # Some distortion special lenses @@ -516,9 +516,6 @@ IncDirectory("ALWAYS", GetOutputDir()+"/include") if (COMPILER == "MSVC"): PkgDisable("X11") - PkgDisable("XRANDR") - PkgDisable("XF86DGA") - PkgDisable("XCURSOR") PkgDisable("GLES") PkgDisable("GLES2") PkgDisable("EGL") @@ -843,9 +840,6 @@ if (COMPILER=="GCC"): SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h") if not RUNTIME: SmartPkgEnable("X11", "x11", "X11", ("X11", "X11/Xlib.h")) - SmartPkgEnable("XRANDR", "xrandr", "Xrandr", "X11/extensions/Xrandr.h") - SmartPkgEnable("XF86DGA", "xxf86dga", "Xxf86dga", "X11/extensions/xf86dga.h") - SmartPkgEnable("XCURSOR", "xcursor", "Xcursor", "X11/Xcursor/Xcursor.h") if GetHost() != "darwin": # Workaround for an issue where pkg-config does not include this path @@ -2194,9 +2188,6 @@ DTOOL_CONFIG=[ ("PHAVE_STDINT_H", '1', '1'), ("HAVE_RTTI", '1', '1'), ("HAVE_X11", 'UNDEF', '1'), - ("HAVE_XRANDR", 'UNDEF', '1'), - ("HAVE_XF86DGA", 'UNDEF', '1'), - ("HAVE_XCURSOR", 'UNDEF', '1'), ("IS_LINUX", 'UNDEF', '1'), ("IS_OSX", 'UNDEF', 'UNDEF'), ("IS_FREEBSD", 'UNDEF', 'UNDEF'), @@ -2301,9 +2292,6 @@ def WriteConfigSettings(): dtool_config["PHAVE_SYS_MALLOC_H"] = '1' dtool_config["HAVE_OPENAL_FRAMEWORK"] = '1' dtool_config["HAVE_X11"] = 'UNDEF' # We might have X11, but we don't need it. - dtool_config["HAVE_XRANDR"] = 'UNDEF' - dtool_config["HAVE_XF86DGA"] = 'UNDEF' - dtool_config["HAVE_XCURSOR"] = 'UNDEF' dtool_config["HAVE_GLX"] = 'UNDEF' dtool_config["IS_LINUX"] = 'UNDEF' dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF' @@ -4581,7 +4569,7 @@ if (GetTarget() not in ['windows', 'darwin'] and PkgSkip("GL")==0 and PkgSkip("X TargetAdd('libpandagl.dll', input='p3glgsg_glgsg.obj') TargetAdd('libpandagl.dll', input='p3glxdisplay_composite1.obj') TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR']) + TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11']) # # DIRECTORY: panda/src/cocoadisplay/ @@ -4656,7 +4644,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTI TargetAdd('libpandagles.dll', input='p3glesgsg_glesgsg.obj') TargetAdd('libpandagles.dll', input='pandagles_egldisplay_composite1.obj') TargetAdd('libpandagles.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR']) + TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11']) # # DIRECTORY: panda/src/egldisplay/ @@ -4674,7 +4662,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0 and not RUNT TargetAdd('libpandagles2.dll', input='p3gles2gsg_gles2gsg.obj') TargetAdd('libpandagles2.dll', input='pandagles2_egldisplay_composite1.obj') TargetAdd('libpandagles2.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR']) + TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11']) # # DIRECTORY: panda/src/ode/ @@ -4970,7 +4958,7 @@ if (not RUNTIME and (GetTarget() in ('windows', 'darwin') or PkgSkip("X11")==0) TargetAdd('libp3tinydisplay.dll', opts=['WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM']) else: TargetAdd('libp3tinydisplay.dll', input='p3x11display_composite1.obj') - TargetAdd('libp3tinydisplay.dll', opts=['X11', 'XRANDR', 'XF86DGA', 'XCURSOR']) + TargetAdd('libp3tinydisplay.dll', opts=['X11']) TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite1.obj') TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite2.obj') TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_ztriangle_1.obj') diff --git a/panda/src/display/get_x11.h b/panda/src/display/get_x11.h index c188164598..f9112766d7 100644 --- a/panda/src/display/get_x11.h +++ b/panda/src/display/get_x11.h @@ -49,19 +49,6 @@ struct XVisualInfo; #include #include #include - -#ifdef HAVE_XRANDR -#include -#endif // HAVE_XRANDR - -#ifdef HAVE_XCURSOR -#include -#endif - -#ifdef HAVE_XF86DGA -#include -#endif - #include "post_x11_include.h" #endif // CPPPARSER diff --git a/panda/src/x11display/config_x11display.cxx b/panda/src/x11display/config_x11display.cxx index 13b225e418..c2b89c42b2 100644 --- a/panda/src/x11display/config_x11display.cxx +++ b/panda/src/x11display/config_x11display.cxx @@ -60,6 +60,11 @@ ConfigVariableInt x_wheel_right_button "mouse button number does the system report when one scrolls " "to the right?")); +ConfigVariableInt x_cursor_size +("x-cursor-size", -1, + PRC_DESC("This sets the cursor size when using XCursor to change the mouse " + "cursor. The default is to use the default size for the display.")); + ConfigVariableString x_wm_class_name ("x-wm-class-name", "", PRC_DESC("Specify the value to use for the res_name field of the window's " diff --git a/panda/src/x11display/config_x11display.h b/panda/src/x11display/config_x11display.h index 88fb2f2133..bc40aad627 100644 --- a/panda/src/x11display/config_x11display.h +++ b/panda/src/x11display/config_x11display.h @@ -32,6 +32,7 @@ extern ConfigVariableInt x_wheel_down_button; extern ConfigVariableInt x_wheel_left_button; extern ConfigVariableInt x_wheel_right_button; +extern ConfigVariableInt x_cursor_size; extern ConfigVariableString x_wm_class_name; extern ConfigVariableString x_wm_class; diff --git a/panda/src/x11display/x11GraphicsPipe.I b/panda/src/x11display/x11GraphicsPipe.I index cb452bef23..fb56700299 100644 --- a/panda/src/x11display/x11GraphicsPipe.I +++ b/panda/src/x11display/x11GraphicsPipe.I @@ -57,6 +57,38 @@ get_hidden_cursor() { return _hidden_cursor; } +/** + * Returns true if relative mouse mode is supported on this display. + */ +INLINE bool x11GraphicsPipe:: +supports_relative_mouse() const { + return (_XF86DGADirectVideo != NULL); +} + +/** + * Enables relative mouse mode for this display. Returns false if unsupported. + */ +INLINE bool x11GraphicsPipe:: +enable_relative_mouse() { + if (_XF86DGADirectVideo != NULL) { + x11display_cat.info() << "Enabling relative mouse using XF86DGA extension\n"; + _XF86DGADirectVideo(_display, _screen, XF86DGADirectMouse); + return true; + } + return false; +} + +/** + * Disables relative mouse mode for this display. + */ +INLINE void x11GraphicsPipe:: +disable_relative_mouse() { + if (_XF86DGADirectVideo != NULL) { + x11display_cat.info() << "Disabling relative mouse using XF86DGA extension\n"; + _XF86DGADirectVideo(_display, _screen, 0); + } +} + /** * Globally disables the printing of error messages that are raised by the X11 * system, for instance in order to test whether a particular X11 operation diff --git a/panda/src/x11display/x11GraphicsPipe.cxx b/panda/src/x11display/x11GraphicsPipe.cxx index 9eee9f6d7a..a0d4e8ffae 100644 --- a/panda/src/x11display/x11GraphicsPipe.cxx +++ b/panda/src/x11display/x11GraphicsPipe.cxx @@ -17,6 +17,8 @@ #include "frameBufferProperties.h" #include "displayInformation.h" +#include + TypeHandle x11GraphicsPipe::_type_handle; bool x11GraphicsPipe::_error_handlers_installed = false; @@ -31,7 +33,11 @@ LightReMutex x11GraphicsPipe::_x_mutex; * */ x11GraphicsPipe:: -x11GraphicsPipe(const string &display) { +x11GraphicsPipe(const string &display) : + _have_xrandr(false), + _xcursor_size(-1), + _XF86DGADirectVideo(NULL) { + string display_spec = display; if (display_spec.empty()) { display_spec = display_cfg; @@ -86,34 +92,116 @@ x11GraphicsPipe(const string &display) { _display_height = DisplayHeight(_display, _screen); _is_valid = true; -#ifdef HAVE_XRANDR - // Use Xrandr to fill in the supported resolution list. - int num_sizes, num_rates; - XRRScreenSize *xrrs; - xrrs = XRRSizes(_display, 0, &num_sizes); - _display_information->_total_display_modes = 0; - for (int i = 0; i < num_sizes; ++i) { - XRRRates(_display, 0, i, &num_rates); - _display_information->_total_display_modes += num_rates; - } + // Dynamically load the xf86dga extension. + void *xf86dga = dlopen("libXxf86dga.so.1", RTLD_NOW | RTLD_LOCAL); + if (xf86dga != NULL) { + pfn_XF86DGAQueryVersion _XF86DGAQueryVersion = (pfn_XF86DGAQueryVersion)dlsym(xf86dga, "XF86DGAQueryVersion"); + _XF86DGADirectVideo = (pfn_XF86DGADirectVideo)dlsym(xf86dga, "XF86DGADirectVideo"); - short *rates; - short counter = 0; - _display_information->_display_mode_array = new DisplayMode[_display_information->_total_display_modes]; - for (int i = 0; i < num_sizes; ++i) { - int num_rates; - rates = XRRRates(_display, 0, i, &num_rates); - for (int j = 0; j < num_rates; ++j) { - DisplayMode* dm = _display_information->_display_mode_array + counter; - dm->width = xrrs[i].width; - dm->height = xrrs[i].height; - dm->refresh_rate = rates[j]; - dm->bits_per_pixel = -1; - dm->fullscreen_only = false; - ++counter; + int major_ver, minor_ver; + if (_XF86DGAQueryVersion == NULL || _XF86DGADirectVideo == NULL) { + x11display_cat.warning() + << "libXxf86dga.so.1 does not provide required functions; relative mouse mode will not work.\n"; + + } else if (!_XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) { + _XF86DGADirectVideo = NULL; + } + } else { + _XF86DGADirectVideo = NULL; + if (x11display_cat.is_debug()) { + x11display_cat.debug() + << "cannot dlopen libXxf86dga.so.1; cursor changing will not work.\n"; + } + } + + // Dynamically load the XCursor extension. + void *xcursor = dlopen("libXcursor.so.1", RTLD_NOW | RTLD_LOCAL); + if (xcursor != NULL) { + pfn_XcursorGetDefaultSize _XcursorGetDefaultSize = (pfn_XcursorGetDefaultSize)dlsym(xcursor, "XcursorGetDefaultSize"); + _XcursorXcFileLoadImages = (pfn_XcursorXcFileLoadImages)dlsym(xcursor, "XcursorXcFileLoadImages"); + _XcursorImagesLoadCursor = (pfn_XcursorImagesLoadCursor)dlsym(xcursor, "XcursorImagesLoadCursor"); + _XcursorImagesDestroy = (pfn_XcursorImagesDestroy)dlsym(xcursor, "XcursorImagesDestroy"); + _XcursorImageCreate = (pfn_XcursorImageCreate)dlsym(xcursor, "XcursorImageCreate"); + _XcursorImageLoadCursor = (pfn_XcursorImageLoadCursor)dlsym(xcursor, "XcursorImageLoadCursor"); + _XcursorImageDestroy = (pfn_XcursorImageDestroy)dlsym(xcursor, "XcursorImageDestroy"); + + if (_XcursorGetDefaultSize == NULL || _XcursorXcFileLoadImages == NULL || + _XcursorImagesLoadCursor == NULL || _XcursorImagesDestroy == NULL || + _XcursorImageCreate == NULL || _XcursorImageLoadCursor == NULL || + _XcursorImageDestroy == NULL) { + _xcursor_size = -1; + x11display_cat.warning() + << "libXcursor.so.1 does not provide required functions; cursor changing will not work.\n"; + + } else if (x_cursor_size.get_value() >= 0) { + _xcursor_size = x_cursor_size; + } else { + _xcursor_size = _XcursorGetDefaultSize(_display); + } + } else { + _xcursor_size = -1; + if (x11display_cat.is_debug()) { + x11display_cat.debug() + << "cannot dlopen libXcursor.so.1; cursor changing will not work.\n"; + } + } + + // Dynamically load the XRandr extension. + void *xrandr = dlopen("libXrandr.so.2", RTLD_NOW | RTLD_LOCAL); + if (xrandr != NULL) { + pfn_XRRQueryExtension _XRRQueryExtension = (pfn_XRRQueryExtension)dlsym(xrandr, "XRRQueryExtension"); + _XRRSizes = (pfn_XRRSizes)dlsym(xrandr, "XRRSizes"); + _XRRRates = (pfn_XRRRates)dlsym(xrandr, "XRRRates"); + _XRRGetScreenInfo = (pfn_XRRGetScreenInfo)dlsym(xrandr, "XRRGetScreenInfo"); + _XRRConfigCurrentConfiguration = (pfn_XRRConfigCurrentConfiguration)dlsym(xrandr, "XRRConfigCurrentConfiguration"); + _XRRSetScreenConfig = (pfn_XRRSetScreenConfig)dlsym(xrandr, "XRRSetScreenConfig"); + + if (_XRRQueryExtension == NULL || _XRRSizes == NULL || _XRRRates == NULL || + _XRRGetScreenInfo == NULL || _XRRConfigCurrentConfiguration == NULL || + _XRRSetScreenConfig == NULL) { + _have_xrandr = false; + x11display_cat.warning() + << "libXrandr.so.2 does not provide required functions; resolution setting will not work.\n"; + } else { + int event, error; + _have_xrandr = _XRRQueryExtension(_display, &event, &error); + } + } else { + _have_xrandr = false; + if (x11display_cat.is_debug()) { + x11display_cat.debug() + << "cannot dlopen libXrandr.so.2; resolution setting will not work.\n"; + } + } + + // Use Xrandr to fill in the supported resolution list. + if (_have_xrandr) { + int num_sizes, num_rates; + XRRScreenSize *xrrs; + xrrs = _XRRSizes(_display, 0, &num_sizes); + _display_information->_total_display_modes = 0; + for (int i = 0; i < num_sizes; ++i) { + _XRRRates(_display, 0, i, &num_rates); + _display_information->_total_display_modes += num_rates; + } + + short *rates; + short counter = 0; + _display_information->_display_mode_array = new DisplayMode[_display_information->_total_display_modes]; + for (int i = 0; i < num_sizes; ++i) { + int num_rates; + rates = _XRRRates(_display, 0, i, &num_rates); + for (int j = 0; j < num_rates; ++j) { + DisplayMode* dm = _display_information->_display_mode_array + counter; + dm->width = xrrs[i].width; + dm->height = xrrs[i].height; + dm->refresh_rate = rates[j]; + dm->bits_per_pixel = -1; + dm->fullscreen_only = false; + ++counter; + } } } -#endif // Connect to an input method for supporting international text entry. _im = XOpenIM(_display, NULL, NULL, NULL); diff --git a/panda/src/x11display/x11GraphicsPipe.h b/panda/src/x11display/x11GraphicsPipe.h index ab06a9b692..4da09d3144 100644 --- a/panda/src/x11display/x11GraphicsPipe.h +++ b/panda/src/x11display/x11GraphicsPipe.h @@ -21,6 +21,22 @@ #include "lightReMutex.h" #include "windowHandle.h" #include "get_x11.h" +#include "config_x11display.h" + +// Excerpt the few definitions we need for the extensions. +#define XF86DGADirectMouse 0x0004 + +typedef struct _XcursorFile XcursorFile; +typedef struct _XcursorImage XcursorImage; +typedef struct _XcursorImages XcursorImages; + +typedef unsigned short Rotation; +typedef unsigned short SizeID; +typedef struct _XRRScreenConfiguration XRRScreenConfiguration; +typedef struct { + int width, height; + int mwidth, mheight; +} XRRScreenSize; class FrameBufferProperties; @@ -40,6 +56,10 @@ public: INLINE X11_Cursor get_hidden_cursor(); + INLINE bool supports_relative_mouse() const; + INLINE bool enable_relative_mouse(); + INLINE void disable_relative_mouse(); + static INLINE int disable_x_error_messages(); static INLINE int enable_x_error_messages(); static INLINE int get_x_error_count(); @@ -61,6 +81,38 @@ public: Atom _net_wm_state_add; Atom _net_wm_state_remove; + // Extension functions. + typedef int (*pfn_XcursorGetDefaultSize)(X11_Display *); + typedef XcursorImages *(*pfn_XcursorXcFileLoadImages)(XcursorFile *, int); + typedef X11_Cursor (*pfn_XcursorImagesLoadCursor)(X11_Display *, const XcursorImages *); + typedef void (*pfn_XcursorImagesDestroy)(XcursorImages *); + typedef XcursorImage *(*pfn_XcursorImageCreate)(int, int); + typedef X11_Cursor (*pfn_XcursorImageLoadCursor)(X11_Display *, const XcursorImage *); + typedef void (*pfn_XcursorImageDestroy)(XcursorImage *); + + int _xcursor_size; + pfn_XcursorXcFileLoadImages _XcursorXcFileLoadImages; + pfn_XcursorImagesLoadCursor _XcursorImagesLoadCursor; + pfn_XcursorImagesDestroy _XcursorImagesDestroy; + pfn_XcursorImageCreate _XcursorImageCreate; + pfn_XcursorImageLoadCursor _XcursorImageLoadCursor; + pfn_XcursorImageDestroy _XcursorImageDestroy; + + typedef Bool (*pfn_XRRQueryExtension)(X11_Display *, int*, int*); + typedef XRRScreenSize *(*pfn_XRRSizes)(X11_Display*, int, int*); + typedef short *(*pfn_XRRRates)(X11_Display*, int, int, int*); + typedef XRRScreenConfiguration *(*pfn_XRRGetScreenInfo)(X11_Display*, X11_Window); + typedef SizeID (*pfn_XRRConfigCurrentConfiguration)(XRRScreenConfiguration*, Rotation*); + typedef Status (*pfn_XRRSetScreenConfig)(X11_Display*, XRRScreenConfiguration *, + Drawable, int, Rotation, Time); + + bool _have_xrandr; + pfn_XRRSizes _XRRSizes; + pfn_XRRRates _XRRRates; + pfn_XRRGetScreenInfo _XRRGetScreenInfo; + pfn_XRRConfigCurrentConfiguration _XRRConfigCurrentConfiguration; + pfn_XRRSetScreenConfig _XRRSetScreenConfig; + protected: X11_Display *_display; int _screen; @@ -69,6 +121,10 @@ protected: X11_Cursor _hidden_cursor; + typedef Bool (*pfn_XF86DGAQueryVersion)(X11_Display *, int*, int*); + typedef Status (*pfn_XF86DGADirectVideo)(X11_Display *, int, int); + pfn_XF86DGADirectVideo _XF86DGADirectVideo; + private: void make_hidden_cursor(); void release_hidden_cursor(); diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index 732932a1e4..3ea2cd3fb0 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -38,7 +38,24 @@ #include #endif -#ifdef HAVE_XCURSOR +struct _XcursorFile { + void *closure; + int (*read)(XcursorFile *, unsigned char *, int); + int (*write)(XcursorFile *, unsigned char *, int); + int (*seek)(XcursorFile *, long, int); +}; + +typedef struct _XcursorImage { + unsigned int version; + unsigned int size; + unsigned int width; + unsigned int height; + unsigned int xhot; + unsigned int yhot; + unsigned int delay; + unsigned int *pixels; +} XcursorImage; + static int xcursor_read(XcursorFile *file, unsigned char *buf, int len) { istream* str = (istream*) file->closure; str->read((char*) buf, len); @@ -66,7 +83,6 @@ static int xcursor_seek(XcursorFile *file, long offset, int whence) { return str->tellg(); } -#endif TypeHandle x11GraphicsWindow::_type_handle; @@ -92,14 +108,14 @@ x11GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, _xwindow = (X11_Window)NULL; _ic = (XIC)NULL; _visual_info = NULL; - -#ifdef HAVE_XRANDR _orig_size_id = -1; - int event, error; - _have_xrandr = XRRQueryExtension(_display, &event, &error); -#else - _have_xrandr = false; -#endif + + if (x11_pipe->_have_xrandr) { + // We may still need these functions after the pipe is already destroyed, + // so we copy them into the x11GraphicsWindow. + _XRRGetScreenInfo = x11_pipe->_XRRGetScreenInfo; + _XRRSetScreenConfig = x11_pipe->_XRRSetScreenConfig; + } _awaiting_configure = false; _dga_mouse_enabled = false; @@ -474,10 +490,9 @@ set_properties_now(WindowProperties &properties) { if (is_fullscreen != want_fullscreen || (is_fullscreen && properties.has_size())) { if (want_fullscreen) { - if (_have_xrandr) { -#ifdef HAVE_XRANDR - XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->get_root()); - SizeID old_size_id = XRRConfigCurrentConfiguration(conf, &_orig_rotation); + if (x11_pipe->_have_xrandr) { + XRRScreenConfiguration* conf = _XRRGetScreenInfo(_display, x11_pipe->get_root()); + SizeID old_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation); SizeID new_size_id = (SizeID) -1; int num_sizes = 0, reqsizex, reqsizey; if (properties.has_size()) { @@ -488,7 +503,7 @@ set_properties_now(WindowProperties &properties) { reqsizey = _properties.get_y_size(); } XRRScreenSize *xrrs; - xrrs = XRRSizes(_display, 0, &num_sizes); + xrrs = x11_pipe->_XRRSizes(_display, 0, &num_sizes); for (int i = 0; i < num_sizes; ++i) { if (xrrs[i].width == reqsizex && xrrs[i].height == reqsizey) { @@ -502,14 +517,13 @@ set_properties_now(WindowProperties &properties) { } else { if (new_size_id != old_size_id) { - XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime); + _XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime); if (_orig_size_id == (SizeID) -1) { // Remember the original resolution so we can switch back to it. _orig_size_id = old_size_id; } } } -#endif } else { // If we don't have Xrandr support, we fake the fullscreen support by // setting the window size to the desktop size. @@ -517,15 +531,13 @@ set_properties_now(WindowProperties &properties) { x11_pipe->get_display_height()); } } else { -#ifdef HAVE_XRANDR // Change the resolution back to what it was. Don't remove the SizeID // typecast! - if (_have_xrandr && _orig_size_id != (SizeID) -1) { - XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->get_root()); - XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), _orig_size_id, _orig_rotation, CurrentTime); + if (_orig_size_id != (SizeID) -1) { + XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, x11_pipe->get_root()); + _XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), _orig_size_id, _orig_rotation, CurrentTime); _orig_size_id = (SizeID) -1; } -#endif // Set the origin back to what it was if (!properties.has_origin() && _properties.has_origin()) { properties.set_origin(_properties.get_x_origin(), _properties.get_y_origin()); @@ -686,23 +698,17 @@ set_properties_now(WindowProperties &properties) { switch (properties.get_mouse_mode()) { case WindowProperties::M_absolute: XUngrabPointer(_display, CurrentTime); -#ifdef HAVE_XF86DGA if (_dga_mouse_enabled) { - x11display_cat.info() << "Disabling relative mouse using XF86DGA extension\n"; - XF86DGADirectVideo(_display, _screen, 0); + x11_pipe->disable_relative_mouse(); _dga_mouse_enabled = false; } -#endif _properties.set_mouse_mode(WindowProperties::M_absolute); properties.clear_mouse_mode(); break; case WindowProperties::M_relative: -#ifdef HAVE_XF86DGA if (!_dga_mouse_enabled) { - int major_ver, minor_ver; - if (XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) { - + if (x11_pipe->supports_relative_mouse()) { X11_Cursor cursor = None; if (_properties.get_cursor_hidden()) { x11GraphicsPipe *x11_pipe; @@ -714,8 +720,7 @@ set_properties_now(WindowProperties &properties) { GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) { x11display_cat.error() << "Failed to grab pointer!\n"; } else { - x11display_cat.info() << "Enabling relative mouse using XF86DGA extension\n"; - XF86DGADirectVideo(_display, _screen, XF86DGADirectMouse); + x11_pipe->enable_relative_mouse(); _properties.set_mouse_mode(WindowProperties::M_relative); properties.clear_mouse_mode(); @@ -730,25 +735,24 @@ set_properties_now(WindowProperties &properties) { _input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y); } } else { - x11display_cat.info() << "XF86DGA extension not available\n"; + x11display_cat.info() + << "XF86DGA extension not available, cannot enable relative mouse mode\n"; _dga_mouse_enabled = false; } } -#endif break; case WindowProperties::M_confined: { -#ifdef HAVE_XF86DGA + x11GraphicsPipe *x11_pipe; + DCAST_INTO_V(x11_pipe, _pipe); + if (_dga_mouse_enabled) { - XF86DGADirectVideo(_display, _screen, 0); + x11_pipe->disable_relative_mouse(); _dga_mouse_enabled = false; } -#endif X11_Cursor cursor = None; if (_properties.get_cursor_hidden()) { - x11GraphicsPipe *x11_pipe; - DCAST_INTO_V(x11_pipe, _pipe); cursor = x11_pipe->get_hidden_cursor(); } @@ -813,10 +817,9 @@ close_window() { XFlush(_display); } -#ifdef HAVE_XRANDR // Change the resolution back to what it was. Don't remove the SizeID // typecast! - if (_have_xrandr && _orig_size_id != (SizeID) -1) { + if (_orig_size_id != (SizeID) -1) { X11_Window root; if (_pipe != NULL) { x11GraphicsPipe *x11_pipe; @@ -827,11 +830,10 @@ close_window() { // closed. Oh well, let's get the root window by ourselves. root = RootWindow(_display, _screen); } - XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, root); - XRRSetScreenConfig(_display, conf, root, _orig_size_id, _orig_rotation, CurrentTime); + XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, root); + _XRRSetScreenConfig(_display, conf, root, _orig_size_id, _orig_rotation, CurrentTime); _orig_size_id = -1; } -#endif GraphicsWindow::close_window(); } @@ -859,15 +861,14 @@ open_window() { _properties.set_size(100, 100); } -#ifdef HAVE_XRANDR - if (_properties.get_fullscreen() && _have_xrandr) { - XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->get_root()); + if (_properties.get_fullscreen() && x11_pipe->_have_xrandr) { + XRRScreenConfiguration* conf = _XRRGetScreenInfo(_display, x11_pipe->get_root()); if (_orig_size_id == (SizeID) -1) { - _orig_size_id = XRRConfigCurrentConfiguration(conf, &_orig_rotation); + _orig_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation); } int num_sizes, new_size_id = -1; XRRScreenSize *xrrs; - xrrs = XRRSizes(_display, 0, &num_sizes); + xrrs = x11_pipe->_XRRSizes(_display, 0, &num_sizes); for (int i = 0; i < num_sizes; ++i) { if (xrrs[i].width == _properties.get_x_size() && xrrs[i].height == _properties.get_y_size()) { @@ -882,12 +883,11 @@ open_window() { return false; } if (new_size_id != _orig_size_id) { - XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime); + _XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime); } else { _orig_size_id = -1; } } -#endif X11_Window parent_window = x11_pipe->get_root(); WindowHandle *window_handle = _properties.get_parent_window(); @@ -2081,11 +2081,15 @@ check_event(X11_Display *display, XEvent *event, char *arg) { */ X11_Cursor x11GraphicsWindow:: get_cursor(const Filename &filename) { -#ifndef HAVE_XCURSOR - x11display_cat.info() - << "XCursor support not enabled in build; cannot change mouse cursor.\n"; - return None; -#else // HAVE_XCURSOR + x11GraphicsPipe *x11_pipe; + DCAST_INTO_R(x11_pipe, _pipe, None); + + if (x11_pipe->_xcursor_size == -1) { + x11display_cat.info() + << "libXcursor.so.1 not available; cannot change mouse cursor.\n"; + return None; + } + // First, look for the unresolved filename in our index. pmap::iterator fi = _cursor_filenames.find(filename); if (fi != _cursor_filenames.end()) { @@ -2135,10 +2139,10 @@ get_cursor(const Filename &filename) { xcfile.write = &xcursor_write; xcfile.seek = &xcursor_seek; - XcursorImages *images = XcursorXcFileLoadImages(&xcfile, XcursorGetDefaultSize(_display)); + XcursorImages *images = x11_pipe->_XcursorXcFileLoadImages(&xcfile, x11_pipe->_xcursor_size); if (images != NULL) { - h = XcursorImagesLoadCursor(_display, images); - XcursorImagesDestroy(images); + h = x11_pipe->_XcursorImagesLoadCursor(_display, images); + x11_pipe->_XcursorImagesDestroy(images); } } else if (memcmp(magic, "\0\0\1\0", 4) == 0 @@ -2159,18 +2163,19 @@ get_cursor(const Filename &filename) { _cursor_filenames[resolved] = h; return h; -#endif // HAVE_XCURSOR } -#ifdef HAVE_XCURSOR /** * Reads a Windows .ico or .cur file from the indicated stream and returns it * as an X11 Cursor. If the file cannot be loaded, returns None. */ X11_Cursor x11GraphicsWindow:: read_ico(istream &ico) { - // Local structs, this is just POD, make input easier - typedef struct { + x11GraphicsPipe *x11_pipe; + DCAST_INTO_R(x11_pipe, _pipe, None); + + // Local structs, this is just POD, make input easier + typedef struct { uint16_t reserved, type, count; } IcoHeader; @@ -2204,7 +2209,7 @@ read_ico(istream &ico) { XcursorImage *image = NULL; X11_Cursor ret = None; - int def_size = XcursorGetDefaultSize(_display); + int def_size = x11_pipe->_xcursor_size; // Get our header, note that ICO = type 1 and CUR = type 2. ico.read(reinterpret_cast(&header), sizeof(IcoHeader)); @@ -2240,7 +2245,7 @@ read_ico(istream &ico) { } img.set_maxval(255); - image = XcursorImageCreate(img.get_x_size(), img.get_y_size()); + image = x11_pipe->_XcursorImageCreate(img.get_x_size(), img.get_y_size()); xel *ptr = img.get_array(); xelval *alpha = img.get_alpha_array(); @@ -2285,7 +2290,7 @@ read_ico(istream &ico) { ico.read(andBmp, andBmpSize); if (!ico.good()) goto cleanup; - image = XcursorImageCreate(infoHeader.width, infoHeader.height / 2); + image = x11_pipe->_XcursorImageCreate(infoHeader.width, infoHeader.height / 2); // Support all the formats that GIMP supports. switch (bitsPerPixel) { @@ -2370,10 +2375,10 @@ read_ico(istream &ico) { image->yhot = 0; } - ret = XcursorImageLoadCursor(_display, image); + ret = x11_pipe->_XcursorImageLoadCursor(_display, image); cleanup: - XcursorImageDestroy(image); + x11_pipe->_XcursorImageDestroy(image); delete[] entries; delete[] palette; delete[] xorBmp; @@ -2381,4 +2386,3 @@ cleanup: return ret; } -#endif // HAVE_XCURSOR diff --git a/panda/src/x11display/x11GraphicsWindow.h b/panda/src/x11display/x11GraphicsWindow.h index fe160284f8..5b55bf3619 100644 --- a/panda/src/x11display/x11GraphicsWindow.h +++ b/panda/src/x11display/x11GraphicsWindow.h @@ -20,11 +20,6 @@ #include "graphicsWindow.h" #include "buttonHandle.h" -#ifdef HAVE_XRANDR -typedef unsigned short Rotation; -typedef unsigned short SizeID; -#endif - /** * Interfaces to the X11 window system. */ @@ -76,9 +71,7 @@ protected: private: X11_Cursor get_cursor(const Filename &filename); -#ifdef HAVE_XCURSOR X11_Cursor read_ico(istream &ico); -#endif protected: X11_Display *_display; @@ -87,12 +80,8 @@ protected: Colormap _colormap; XIC _ic; XVisualInfo *_visual_info; - - bool _have_xrandr; -#ifdef HAVE_XRANDR Rotation _orig_rotation; SizeID _orig_size_id; -#endif LVecBase2i _fixed_size; @@ -109,6 +98,9 @@ protected: }; pvector _mouse_device_info; + x11GraphicsPipe::pfn_XRRGetScreenInfo _XRRGetScreenInfo; + x11GraphicsPipe::pfn_XRRSetScreenConfig _XRRSetScreenConfig; + public: static TypeHandle get_class_type() { return _type_handle; From 45356e85e148f40d4111ce9b101aeae1d5954c88 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 25 Dec 2016 11:48:38 +0100 Subject: [PATCH 44/70] Backward compat with older OpenSSL versions --- dtool/src/prc/encryptStreamBuf.cxx | 27 +++++++-------------------- panda/src/downloader/httpClient.cxx | 8 ++++++++ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/dtool/src/prc/encryptStreamBuf.cxx b/dtool/src/prc/encryptStreamBuf.cxx index fed8b8e7b6..6cb0ee6b39 100644 --- a/dtool/src/prc/encryptStreamBuf.cxx +++ b/dtool/src/prc/encryptStreamBuf.cxx @@ -111,6 +111,11 @@ open_read(istream *source, bool owns_source, const string &password) { _source = source; _owns_source = owns_source; + if (_read_ctx != NULL) { + EVP_CIPHER_CTX_free(_read_ctx); + _read_ctx = NULL; + } + // Now read the header information. StreamReader sr(_source, false); int nid = sr.get_uint16(); @@ -122,11 +127,6 @@ open_read(istream *source, bool owns_source, const string &password) { if (cipher == NULL) { prc_cat.error() << "Unknown encryption algorithm in stream.\n"; - - if (_read_ctx != NULL) { - EVP_CIPHER_CTX_free(_read_ctx); - _read_ctx = NULL; - } return; } @@ -147,11 +147,7 @@ open_read(istream *source, bool owns_source, const string &password) { string iv = sr.extract_bytes(iv_length); - if (_read_ctx != NULL) { - EVP_CIPHER_CTX_reset(_read_ctx); - } else { - _read_ctx = EVP_CIPHER_CTX_new(); - } + _read_ctx = EVP_CIPHER_CTX_new(); nassertv(_read_ctx != NULL); // Initialize the context @@ -228,11 +224,6 @@ open_write(ostream *dest, bool owns_dest, const string &password) { if (cipher == NULL) { prc_cat.error() << "Unknown encryption algorithm: " << _algorithm << "\n"; - - if (_write_ctx != NULL) { - EVP_CIPHER_CTX_free(_write_ctx); - _write_ctx = NULL; - } return; } @@ -246,11 +237,7 @@ open_write(ostream *dest, bool owns_dest, const string &password) { unsigned char *iv = (unsigned char *)alloca(iv_length); RAND_pseudo_bytes(iv, iv_length); - if (_read_ctx != NULL) { - EVP_CIPHER_CTX_reset(_write_ctx); - } else { - _write_ctx = EVP_CIPHER_CTX_new(); - } + _write_ctx = EVP_CIPHER_CTX_new(); nassertv(_write_ctx != NULL); int result; diff --git a/panda/src/downloader/httpClient.cxx b/panda/src/downloader/httpClient.cxx index f1ae5d7e7c..63ba1c6258 100644 --- a/panda/src/downloader/httpClient.cxx +++ b/panda/src/downloader/httpClient.cxx @@ -232,6 +232,12 @@ operator = (const HTTPClient ©) { HTTPClient:: ~HTTPClient() { if (_ssl_ctx != (SSL_CTX *)NULL) { +#if OPENSSL_VERSION_NUMBER < 0x10100000 + // Before we can free the context, we must remove the X509_STORE pointer + // from it, so it won't be destroyed along with it (this object is shared + // among all contexts). + _ssl_ctx->cert_store = NULL; +#endif SSL_CTX_free(_ssl_ctx); } @@ -1119,9 +1125,11 @@ get_ssl_ctx() { sslw->notify_ssl_errors(); X509_STORE *store = sslw->get_x509_store(); +#if OPENSSL_VERSION_NUMBER >= 0x10100000 if (store != NULL) { X509_STORE_up_ref(store); } +#endif SSL_CTX_set_cert_store(_ssl_ctx, store); return _ssl_ctx; From 59c3aa3ef6a090592b7ee32e7b4ca229c6ffe649 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 25 Dec 2016 09:59:29 -0500 Subject: [PATCH 45/70] cocoa: don't crash if display server doesn't give us display modes --- panda/src/cocoadisplay/cocoaGraphicsPipe.mm | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm index 1969ac4116..367b00c520 100644 --- a/panda/src/cocoadisplay/cocoaGraphicsPipe.mm +++ b/panda/src/cocoadisplay/cocoaGraphicsPipe.mm @@ -148,11 +148,14 @@ load_display_information() { //_display_information->_device_id = CGDisplaySerialNumber(_display); // Display modes + size_t num_modes = 0; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, NULL); - size_t num_modes = CFArrayGetCount(modes); - _display_information->_total_display_modes = num_modes; - _display_information->_display_mode_array = new DisplayMode[num_modes]; + if (modes != NULL) { + num_modes = CFArrayGetCount(modes); + _display_information->_total_display_modes = num_modes; + _display_information->_display_mode_array = new DisplayMode[num_modes]; + } for (size_t i = 0; i < num_modes; ++i) { CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); @@ -189,13 +192,17 @@ load_display_information() { } CFRelease(encoding); } - CFRelease(modes); + if (modes != NULL) { + CFRelease(modes); + } #else CFArrayRef modes = CGDisplayAvailableModes(_display); - size_t num_modes = CFArrayGetCount(modes); - _display_information->_total_display_modes = num_modes; - _display_information->_display_mode_array = new DisplayMode[num_modes]; + if (modes != NULL) { + num_modes = CFArrayGetCount(modes); + _display_information->_total_display_modes = num_modes; + _display_information->_display_mode_array = new DisplayMode[num_modes]; + } for (size_t i = 0; i < num_modes; ++i) { CFDictionaryRef mode = (CFDictionaryRef) CFArrayGetValueAtIndex(modes, i); From 23a345437a0edd7fcb1b3a1585d847f6134dfe49 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 25 Dec 2016 16:10:06 +0100 Subject: [PATCH 46/70] makewheel changes for macOS, manylinux1, Python 2.6 --- makepanda/makewheel.py | 139 ++++++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 58 deletions(-) diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index 81caf24701..dda4bc75e0 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -3,9 +3,11 @@ Generates a wheel (.whl) file from the output of makepanda. Since the wheel requires special linking, this will only work if compiled with the `--wheel` parameter. + +Please keep this file work with Panda3D 1.9 until that reaches EOL. """ from __future__ import print_function, unicode_literals -from distutils.util import get_platform as get_dist +from distutils.util import get_platform import json import sys @@ -16,20 +18,18 @@ import zipfile import hashlib import tempfile import subprocess -from sysconfig import get_config_var +from distutils.sysconfig import get_config_var from optparse import OptionParser from makepandacore import ColorText, LocateBinary, ParsePandaVersion, GetExtensionSuffix, SetVerbose, GetVerbose from base64 import urlsafe_b64encode -def get_platform(): - p = get_dist().replace('-', '_').replace('.', '_') - #if "linux" in p: - # print(ColorText("red", "WARNING:") + - # " Linux-specific wheel files are not supported." - # " We will generate this wheel as a generic package instead.") - # return "any" - return p +default_platform = get_platform() + +if default_platform.startswith("linux-"): + # Is this manylinux1? + if os.path.isfile("/lib/libc-2.5.so") and os.path.isdir("/opt/python"): + default_platform = platform.replace("linux", "manylinux1") def get_abi_tag(): @@ -71,7 +71,9 @@ def is_elf_file(path): def is_mach_o_file(path): base = os.path.basename(path) return os.path.isfile(path) and '.' not in base and \ - open(path, 'rb').read(4) == b'\xCA\xFE\xBA\xBE' + open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA', + b'\xFE\xED\xFA\xCE', b'\xCE\xFA\xED\xFE', + b'\xFE\xED\xFA\xCF', b'\xCF\xFA\xED\xFE') if sys.platform in ('win32', 'cygwin'): @@ -83,18 +85,17 @@ else: # Other global parameters -PY_VERSION = "cp{}{}".format(sys.version_info.major, sys.version_info.minor) +PY_VERSION = "cp{0}{1}".format(*sys.version_info) ABI_TAG = get_abi_tag() -PLATFORM_TAG = get_platform() EXCLUDE_EXT = [".pyc", ".pyo", ".N", ".prebuilt", ".xcf", ".plist", ".vcproj", ".sln"] # Plug-ins to install. -PLUGIN_LIBS = ["pandagl", "pandagles", "pandagles2", "p3ptloader", "p3assimp", "p3ffmpeg", "p3openal_audio", "p3fmod_audio"] +PLUGIN_LIBS = ["pandagl", "pandagles", "pandagles2", "pandadx9", "p3tinydisplay", "p3ptloader", "p3assimp", "p3ffmpeg", "p3openal_audio", "p3fmod_audio"] WHEEL_DATA = """Wheel-Version: 1.0 Generator: makepanda Root-Is-Purelib: false -Tag: {}-{}-{} +Tag: {0}-{1}-{2} """ METADATA = { @@ -234,7 +235,11 @@ def scan_dependencies(pathname): else: command = ['ldd', pathname] - output = subprocess.check_output(command, universal_newlines=True) + process = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True) + output, unused_err = process.communicate() + retcode = process.poll() + if retcode: + raise subprocess.CalledProcessError(retcode, command[0], output=output) filenames = None if sys.platform in ("win32", "cygwin"): @@ -245,16 +250,21 @@ def scan_dependencies(pathname): if filenames is None: sys.exit("Unable to determine dependencies from %s" % (pathname)) + if sys.platform == "darwin" and len(filenames) > 0: + # Filter out the library ID. + if os.path.basename(filenames[0]).split('.', 1)[0] == os.path.basename(pathname).split('.', 1)[0]: + del filenames[0] + return filenames class WheelFile(object): - def __init__(self, name, version): + def __init__(self, name, version, platform): self.name = name self.version = version - wheel_name = "{}-{}-{}-{}-{}.whl".format( - name, version, PY_VERSION, ABI_TAG, PLATFORM_TAG) + wheel_name = "{0}-{1}-{2}-{3}-{4}.whl".format( + name, version, PY_VERSION, ABI_TAG, platform) print("Writing %s" % (wheel_name)) self.zip_file = zipfile.ZipFile(wheel_name, 'w', zipfile.ZIP_DEFLATED) @@ -279,6 +289,10 @@ class WheelFile(object): # Don't include the Python library. return + if sys.platform == "darwin" and dep.endswith(".so"): + # Temporary hack for 1.9, which had link deps on modules. + return + source_path = None if search_path is None: @@ -372,7 +386,7 @@ class WheelFile(object): # Save it in PEP-0376 format for writing out later. digest = str(urlsafe_b64encode(sha.digest())) digest = digest.rstrip('=') - self.records.append("{},sha256={},{}\n".format(target_path, digest, size)) + self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, size)) if GetVerbose(): print("Adding %s from %s" % (target_path, source_path)) @@ -388,7 +402,7 @@ class WheelFile(object): sha.update(source_data.encode()) digest = str(urlsafe_b64encode(sha.digest())) digest = digest.rstrip('=') - self.records.append("{},sha256={},{}\n".format(target_path, digest, len(source_data))) + self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, len(source_data))) if GetVerbose(): print("Adding %s from data" % target_path) @@ -409,18 +423,20 @@ class WheelFile(object): def close(self): # Write the RECORD file. - record_file = "{}-{}.dist-info/RECORD".format(self.name, self.version) + record_file = "{0}-{1}.dist-info/RECORD".format(self.name, self.version) self.records.append(record_file + ",,\n") self.zip_file.writestr(record_file, "".join(self.records)) self.zip_file.close() -def makewheel(version, output_dir): +def makewheel(version, output_dir, platform=default_platform): if sys.platform not in ("win32", "darwin") and not sys.platform.startswith("cygwin"): if not LocateBinary("patchelf"): raise Exception("patchelf is required when building a Linux wheel.") + platform = platform.replace('-', '_').replace('.', '_') + # Global filepaths panda3d_dir = join(output_dir, "panda3d") pandac_dir = join(output_dir, "pandac") @@ -438,8 +454,8 @@ def makewheel(version, output_dir): # Update relevant METADATA entries METADATA['version'] = version version_classifiers = [ - "Programming Language :: Python :: {}".format(*sys.version_info), - "Programming Language :: Python :: {}.{}".format(*sys.version_info), + "Programming Language :: Python :: {0}".format(*sys.version_info), + "Programming Language :: Python :: {0}.{1}".format(*sys.version_info), ] METADATA['classifiers'].extend(version_classifiers) @@ -454,14 +470,14 @@ def makewheel(version, output_dir): "Version: {version}\n" \ "Summary: {summary}\n" \ "License: {license}\n".format(**METADATA), - "Home-page: {}\n".format(homepage), - "Author: {}\n".format(author), - "Author-email: {}\n".format(email), - "Platform: {}\n".format(PLATFORM_TAG), - ] + ["Classifier: {}\n".format(c) for c in METADATA['classifiers']]) + "Home-page: {0}\n".format(homepage), + "Author: {0}\n".format(author), + "Author-email: {0}\n".format(email), + "Platform: {0}\n".format(platform), + ] + ["Classifier: {0}\n".format(c) for c in METADATA['classifiers']]) # Zip it up and name it the right thing - whl = WheelFile('panda3d', version) + whl = WheelFile('panda3d', version, platform) whl.lib_path = [libs_dir] # Add the trees with Python modules. @@ -479,11 +495,12 @@ def makewheel(version, output_dir): elif file.endswith(ext_suffix) or file.endswith('.py'): source_path = os.path.join(panda3d_dir, file) - if file.endswith('.pyd') and PLATFORM_TAG.startswith('cygwin'): + if file.endswith('.pyd') and platform.startswith('cygwin'): # Rename it to .dll for cygwin Python to be able to load it. target_path = 'panda3d/' + os.path.splitext(file)[0] + '.dll' else: target_path = 'panda3d/' + file + whl.write_file(target_path, source_path) # Add plug-ins. @@ -499,31 +516,8 @@ def makewheel(version, output_dir): if os.path.isfile(plugin_path): whl.write_file('panda3d/' + plugin_name, plugin_path) - # Add the pandac tree for backward compatibility. - for file in os.listdir(pandac_dir): - if file.endswith('.py'): - whl.write_file('pandac/' + file, os.path.join(pandac_dir, file)) - - # Add a panda3d-tools directory containing the executables. - entry_points = '[console_scripts]\n' - tools_init = '' - for file in os.listdir(bin_dir): - source_path = os.path.join(bin_dir, file) - - if is_executable(source_path): - # Put the .exe files inside the panda3d-tools directory. - whl.write_file('panda3d_tools/' + file, source_path) - - # Tell pip to create a wrapper script. - basename = os.path.splitext(file)[0] - 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) - - whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init)) - # Add the .data directory, containing additional files. - data_dir = 'panda3d-{}.data'.format(version) + data_dir = 'panda3d-{0}.data'.format(version) #whl.write_directory(data_dir + '/data/etc', etc_dir) #whl.write_directory(data_dir + '/data/models', models_dir) @@ -532,12 +526,40 @@ def makewheel(version, output_dir): whl.write_directory('panda3d/etc', etc_dir) whl.write_directory('panda3d/models', models_dir) + # Add the pandac tree for backward compatibility. + for file in os.listdir(pandac_dir): + if file.endswith('.py'): + whl.write_file('pandac/' + file, os.path.join(pandac_dir, file)) + + # Add a panda3d-tools directory containing the executables. + entry_points = '[console_scripts]\n' + entry_points += 'eggcacher = direct.directscripts.eggcacher:main\n' + entry_points += 'packpanda = direct.directscripts.packpanda:main\n' + tools_init = '' + for file in os.listdir(bin_dir): + basename = os.path.splitext(file)[0] + if basename in ('eggcacher', 'packpanda'): + continue + + source_path = os.path.join(bin_dir, file) + + if is_executable(source_path): + # Put the .exe files inside the panda3d-tools directory. + whl.write_file('panda3d_tools/' + file, source_path) + + # 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) + + whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init)) + # Add the dist-info directory last. - info_dir = 'panda3d-{}.dist-info'.format(version) + info_dir = 'panda3d-{0}.dist-info'.format(version) whl.write_file_data(info_dir + '/entry_points.txt', entry_points) whl.write_file_data(info_dir + '/metadata.json', json.dumps(METADATA, indent=4, separators=(',', ': '))) whl.write_file_data(info_dir + '/METADATA', metadata) - whl.write_file_data(info_dir + '/WHEEL', WHEEL_DATA.format(PY_VERSION, ABI_TAG, PLATFORM_TAG)) + whl.write_file_data(info_dir + '/WHEEL', WHEEL_DATA.format(PY_VERSION, ABI_TAG, platform)) whl.write_file(info_dir + '/LICENSE.txt', license_src) whl.write_file(info_dir + '/README.md', readme_src) whl.write_file_data(info_dir + '/top_level.txt', 'direct\npanda3d\npandac\npanda3d_tools\n') @@ -552,6 +574,7 @@ if __name__ == "__main__": parser.add_option('', '--version', dest = 'version', help = 'Panda3D version number (default: %s)' % (version), default = version) parser.add_option('', '--outputdir', dest = 'outputdir', help = 'Makepanda\'s output directory (default: built)', default = 'built') parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False) + parser.add_option('', '--platform', dest = 'platform', help = 'Override platform tag (default: %s)' % (default_platform), default = get_platform()) (options, args) = parser.parse_args() SetVerbose(options.verbose) From 4393455ebac4fd4c65febc5d5bf7dde862117978 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 25 Dec 2016 16:12:54 +0100 Subject: [PATCH 47/70] Fix get_keyboard_map on Czech (and other) layouts Now reports proper Unicode name, and doesn't omit keys that don't have a recognised mapping by Panda https://bugs.launchpad.net/panda3d/+bug/1652145 --- doc/ReleaseNotes | 1 + panda/src/windisplay/winGraphicsWindow.cxx | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 3ad0ecd49b..cd6bdf2f4c 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -52,6 +52,7 @@ This issue fixes several bugs that were still found in 1.9.2. * Now tries to preserve refresh rate when switching fullscreen on Windows * Fix back-to-front sorting when gl-coordinate-system is changed * Now also compiles on older Linux distros (eg. CentOS 5 / manylinux1) +* get_keyboard_map now includes keys on layouts with special characters ------------------------ RELEASE 1.9.2 ------------------------ diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 0f7e33dc75..7f949415fe 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -2721,7 +2721,7 @@ ButtonMap *WinGraphicsWindow:: get_keyboard_map() const { ButtonMap *map = new ButtonMap; - char text[256]; + wchar_t text[256]; UINT vsc = 0; unsigned short ex_vsc[] = {0x57, 0x58, 0x011c, 0x011d, 0x0135, 0x0137, 0x0138, 0x0145, 0x0147, 0x0148, 0x0149, 0x014b, 0x014d, 0x014f, 0x0150, 0x0151, 0x0152, 0x0153, 0x015b, 0x015c, 0x015d}; @@ -2759,14 +2759,15 @@ get_keyboard_map() const { UINT vk = MapVirtualKeyA(vsc, MAPVK_VSC_TO_VK_EX); button = lookup_key(vk); - if (button == ButtonHandle::none()) { - continue; - } + //if (button == ButtonHandle::none()) { + // continue; + //} } - int len = GetKeyNameTextA(lparam, text, 256); - string label (text, len); - map->map_button(raw_button, button, label); + int len = GetKeyNameTextW(lparam, text, 256); + TextEncoder enc; + enc.set_wtext(wstring(text, len)); + map->map_button(raw_button, button, enc.get_text()); } return map; From 0c742d59e58dd4c7a5a608e5d243d42319a7357a Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 25 Dec 2016 22:03:05 +0100 Subject: [PATCH 48/70] Fix crash due to incorrect alignment when building Eigen with AVX extensions Consequentially, we now use 32-byte alignment when building with eigen if __AVX__ is set. --- doc/ReleaseNotes | 1 + dtool/src/dtoolbase/deletedBufferChain.h | 4 ++++ dtool/src/dtoolbase/dlmalloc_src.cxx | 5 +++++ dtool/src/dtoolbase/dtoolbase.h | 2 +- dtool/src/dtoolbase/memoryHook.I | 12 +++++++++++- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index cd6bdf2f4c..74a0a9ea05 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -53,6 +53,7 @@ This issue fixes several bugs that were still found in 1.9.2. * Fix back-to-front sorting when gl-coordinate-system is changed * Now also compiles on older Linux distros (eg. CentOS 5 / manylinux1) * get_keyboard_map now includes keys on layouts with special characters +* Fix crash due to incorrect alignment when compiling Eigen with AVX ------------------------ RELEASE 1.9.2 ------------------------ diff --git a/dtool/src/dtoolbase/deletedBufferChain.h b/dtool/src/dtoolbase/deletedBufferChain.h index 301ee5d297..a71bc90b45 100644 --- a/dtool/src/dtoolbase/deletedBufferChain.h +++ b/dtool/src/dtoolbase/deletedBufferChain.h @@ -105,7 +105,11 @@ private: #elif defined(LINMATH_ALIGN) // With SSE2 alignment, we need all 16 bytes to preserve alignment. +#ifdef __AVX__ + static const size_t flag_reserved_bytes = 32; +#else static const size_t flag_reserved_bytes = 16; +#endif #else // Otherwise, we only need enough space for the Integer itself. diff --git a/dtool/src/dtoolbase/dlmalloc_src.cxx b/dtool/src/dtoolbase/dlmalloc_src.cxx index 4e21f4c914..dcbb0daa25 100644 --- a/dtool/src/dtoolbase/dlmalloc_src.cxx +++ b/dtool/src/dtoolbase/dlmalloc_src.cxx @@ -453,8 +453,13 @@ DEFAULT_MMAP_THRESHOLD default: 256K // drose: We require 16-byte alignment of certain structures, to // support SSE2. We don't strictly have to align *everything*, but // it's just easier to do so. +#ifdef __AVX__ +// Eigen requires 32-byte alignment when using AVX instructions. +#define MALLOC_ALIGNMENT ((size_t)32U) +#else #define MALLOC_ALIGNMENT ((size_t)16U) #endif +#endif #ifndef WIN32 #ifdef _WIN32 diff --git a/dtool/src/dtoolbase/dtoolbase.h b/dtool/src/dtoolbase/dtoolbase.h index 2c883f8220..27add7c84d 100644 --- a/dtool/src/dtoolbase/dtoolbase.h +++ b/dtool/src/dtoolbase/dtoolbase.h @@ -372,7 +372,7 @@ // enforce alignment externally. #define MEMORY_HOOK_DO_ALIGN 1 -#elif defined(IS_OSX) || defined(_WIN64) +#elif (defined(IS_OSX) || defined(_WIN64)) && !defined(__AVX__) // The OS-provided malloc implementation will do the required // alignment. #undef MEMORY_HOOK_DO_ALIGN diff --git a/dtool/src/dtoolbase/memoryHook.I b/dtool/src/dtoolbase/memoryHook.I index 9286a18d7a..ecccf07d65 100644 --- a/dtool/src/dtoolbase/memoryHook.I +++ b/dtool/src/dtoolbase/memoryHook.I @@ -55,7 +55,12 @@ get_memory_alignment() { // We require 16-byte alignment of certain structures, to support // SSE2. We don't strictly have to align *everything*, but it's just // easier to do so. +#ifdef __AVX__ + // Eigen requires 32-byte alignment when using AVX instructions. + const size_t alignment_size = 32; +#else const size_t alignment_size = 16; +#endif #else // Otherwise, use word alignment. const size_t alignment_size = sizeof(void *); @@ -79,7 +84,12 @@ get_header_reserved_bytes() { #ifdef LINMATH_ALIGN // If we're doing SSE2 alignment, we must reserve a full 16-byte // block, since anything less than that will spoil the alignment. - static const size_t header_reserved_bytes = 16; +#ifdef __AVX__ + // Eigen requires 32-byte alignment when using AVX instructions. + const size_t header_reserved_bytes = 32; +#else + const size_t header_reserved_bytes = 16; +#endif #elif defined(MEMORY_HOOK_DO_ALIGN) // If we're just aligning to words, we reserve a block as big as two From 741ff454ed951603145a00c85c52252c55c7f48f Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 25 Dec 2016 22:53:21 +0100 Subject: [PATCH 49/70] We need to link tools that use interrogatedb with pystub again --- makepanda/makepanda.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 8854faecd1..95dc6d791b 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -3337,6 +3337,7 @@ if (not RUNTIME): TargetAdd('interrogate.exe', input='libp3cppParser.ilb') TargetAdd('interrogate.exe', input=COMMON_DTOOL_LIBS) TargetAdd('interrogate.exe', input='libp3interrogatedb.dll') + TargetAdd('interrogate.exe', input='libp3pystub.lib') TargetAdd('interrogate.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER']) TargetAdd('interrogate_module_interrogate_module.obj', opts=OPTS, input='interrogate_module.cxx') @@ -3344,6 +3345,7 @@ if (not RUNTIME): TargetAdd('interrogate_module.exe', input='libp3cppParser.ilb') TargetAdd('interrogate_module.exe', input=COMMON_DTOOL_LIBS) TargetAdd('interrogate_module.exe', input='libp3interrogatedb.dll') + TargetAdd('interrogate_module.exe', input='libp3pystub.lib') TargetAdd('interrogate_module.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER']) if (not RTDIST): @@ -3352,6 +3354,7 @@ if (not RUNTIME): TargetAdd('parse_file.exe', input='libp3cppParser.ilb') TargetAdd('parse_file.exe', input=COMMON_DTOOL_LIBS) TargetAdd('parse_file.exe', input='libp3interrogatedb.dll') + TargetAdd('parse_file.exe', input='libp3pystub.lib') TargetAdd('parse_file.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER']) # @@ -3375,6 +3378,7 @@ if (not RTDIST and not RUNTIME): TargetAdd('test_interrogate.exe', input='test_interrogate_test_interrogate.obj') TargetAdd('test_interrogate.exe', input='libp3interrogatedb.dll') TargetAdd('test_interrogate.exe', input=COMMON_DTOOL_LIBS) + TargetAdd('test_interrogate.exe', input='libp3pystub.lib') TargetAdd('test_interrogate.exe', opts=['ADVAPI', 'OPENSSL', 'WINSHELL', 'WINGDI', 'WINUSER']) # @@ -5160,6 +5164,7 @@ if (PkgSkip("PYTHON")==0 and PkgSkip("DIRECT")==0 and not RTDIST and not RUNTIME TargetAdd('p3dcparse.exe', input='dcparse_dcparse.obj') TargetAdd('p3dcparse.exe', input='libp3direct.dll') TargetAdd('p3dcparse.exe', input=COMMON_PANDA_LIBS) + TargetAdd('p3dcparse.exe', input='libp3pystub.lib') TargetAdd('p3dcparse.exe', opts=['ADVAPI', 'PYTHON']) # From 9c789db9183342f80a00d8d23e6f4f94fd70ea41 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 25 Dec 2016 23:58:08 +0100 Subject: [PATCH 50/70] Compile fix for Python 3.2 --- dtool/src/pystub/pystub.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dtool/src/pystub/pystub.cxx b/dtool/src/pystub/pystub.cxx index 4f2e74144a..d0d6a4ca1a 100644 --- a/dtool/src/pystub/pystub.cxx +++ b/dtool/src/pystub/pystub.cxx @@ -149,12 +149,14 @@ extern "C" { EXPCL_PYSTUB int PyUnicodeUCS2_FromStringAndSize(...); EXPCL_PYSTUB int PyUnicodeUCS2_FromWideChar(...); EXPCL_PYSTUB int PyUnicodeUCS2_AsWideChar(...); + EXPCL_PYSTUB int PyUnicodeUCS2_AsWideCharString(...); EXPCL_PYSTUB int PyUnicodeUCS2_GetSize(...); EXPCL_PYSTUB int PyUnicodeUCS4_FromFormat(...); EXPCL_PYSTUB int PyUnicodeUCS4_FromString(...); EXPCL_PYSTUB int PyUnicodeUCS4_FromStringAndSize(...); EXPCL_PYSTUB int PyUnicodeUCS4_FromWideChar(...); EXPCL_PYSTUB int PyUnicodeUCS4_AsWideChar(...); + EXPCL_PYSTUB int PyUnicodeUCS4_AsWideCharString(...); EXPCL_PYSTUB int PyUnicodeUCS4_GetSize(...); EXPCL_PYSTUB int PyUnicode_AsUTF8(...); EXPCL_PYSTUB int PyUnicode_AsUTF8AndSize(...); @@ -349,12 +351,14 @@ int PyUnicodeUCS2_FromString(...) { return 0; } int PyUnicodeUCS2_FromStringAndSize(...) { return 0; } int PyUnicodeUCS2_FromWideChar(...) { return 0; } int PyUnicodeUCS2_AsWideChar(...) { return 0; } +int PyUnicodeUCS2_AsWideCharString(...) { return 0; } int PyUnicodeUCS2_GetSize(...) { return 0; } int PyUnicodeUCS4_FromFormat(...) { return 0; } int PyUnicodeUCS4_FromString(...) { return 0; } int PyUnicodeUCS4_FromStringAndSize(...) { return 0; } int PyUnicodeUCS4_FromWideChar(...) { return 0; } int PyUnicodeUCS4_AsWideChar(...) { return 0; } +int PyUnicodeUCS4_AsWideCharString(...) { return 0; } int PyUnicodeUCS4_GetSize(...) { return 0; } int PyUnicode_AsUTF8(...) { return 0; } int PyUnicode_AsUTF8AndSize(...) { return 0; } From fb2568afada31088bf7e19e5de1033ba9d8d8f2b Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 26 Dec 2016 17:36:11 +0100 Subject: [PATCH 51/70] Fix faulty merge --- doc/ReleaseNotes | 2 +- dtool/src/dtoolbase/memoryHook.I | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 74a0a9ea05..d3e22a1fc3 100644 --- a/doc/ReleaseNotes +++ b/doc/ReleaseNotes @@ -54,6 +54,7 @@ This issue fixes several bugs that were still found in 1.9.2. * Now also compiles on older Linux distros (eg. CentOS 5 / manylinux1) * get_keyboard_map now includes keys on layouts with special characters * Fix crash due to incorrect alignment when compiling Eigen with AVX +* Fix crash when writing 16-bit .tif file (now silently downsamples) ------------------------ RELEASE 1.9.2 ------------------------ @@ -78,7 +79,6 @@ remained in the 1.9.1 release, including: * Fix constant reloading of texture when gl-ignore-mipmaps is set * BamReader now releases the GIL (so it can be used threaded) * Fix AttributeError in direct.stdpy.threading module -* Fix crash when writing 16-bit .tif file (now silently downsamples) ------------------------ RELEASE 1.9.1 ------------------------ diff --git a/dtool/src/dtoolbase/memoryHook.I b/dtool/src/dtoolbase/memoryHook.I index d22a51ad48..3d2be05097 100644 --- a/dtool/src/dtoolbase/memoryHook.I +++ b/dtool/src/dtoolbase/memoryHook.I @@ -70,12 +70,11 @@ get_header_reserved_bytes() { #ifdef LINMATH_ALIGN // If we're doing SSE2 alignment, we must reserve a full 16-byte block, // since anything less than that will spoil the alignment. - static const size_t header_reserved_bytes = 16; #ifdef __AVX__ // Eigen requires 32-byte alignment when using AVX instructions. - const size_t header_reserved_bytes = 32; + static const size_t header_reserved_bytes = 32; #else - const size_t header_reserved_bytes = 16; + static const size_t header_reserved_bytes = 16; #endif #elif defined(MEMORY_HOOK_DO_ALIGN) From 325302b6239d264a1679c1f146f5ee06bfcab1f1 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 26 Dec 2016 17:36:38 +0100 Subject: [PATCH 52/70] makewheel: support building single-arch .whl from a fat Panda build --- makepanda/makewheel.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index dda4bc75e0..6d3b6fdf72 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -29,7 +29,7 @@ default_platform = get_platform() if default_platform.startswith("linux-"): # Is this manylinux1? if os.path.isfile("/lib/libc-2.5.so") and os.path.isdir("/opt/python"): - default_platform = platform.replace("linux", "manylinux1") + default_platform = default_platform.replace("linux", "manylinux1") def get_abi_tag(): @@ -75,6 +75,10 @@ def is_mach_o_file(path): b'\xFE\xED\xFA\xCE', b'\xCE\xFA\xED\xFE', b'\xFE\xED\xFA\xCF', b'\xCF\xFA\xED\xFE') +def is_fat_file(path): + return os.path.isfile(path) and \ + open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA') + if sys.platform in ('win32', 'cygwin'): is_executable = is_exe_file @@ -262,6 +266,7 @@ class WheelFile(object): def __init__(self, name, version, platform): self.name = name self.version = version + self.platform = platform wheel_name = "{0}-{1}-{2}-{3}-{4}.whl".format( name, version, PY_VERSION, ABI_TAG, platform) @@ -285,7 +290,7 @@ class WheelFile(object): self.dep_paths[dep] = None - if dep.lower().startswith("python"): + if dep.lower().startswith("python") or os.path.basename(dep).startswith("libpython"): # Don't include the Python library. return @@ -339,6 +344,18 @@ class WheelFile(object): suffix = '.dylib' temp = tempfile.NamedTemporaryFile(suffix=suffix, prefix='whl', delete=False) + + # On macOS, if no fat wheel was requested, extract the right architecture. + if sys.platform == "darwin" and is_fat_file(source_path) and not self.platform.endswith("_intel"): + if self.platform.endswith("_x86_64"): + arch = 'x86_64' + else: + arch = self.platform.split('_')[-1] + subprocess.call(['lipo', source_path, '-extract', arch, '-output', temp.name]) + else: + # Otherwise, just copy it over. + temp.write(open(source_path, 'rb').read()) + temp.write(open(source_path, 'rb').read()) os.fchmod(temp.fileno(), os.fstat(temp.fileno()).st_mode | 0o111) temp.close() @@ -578,4 +595,4 @@ if __name__ == "__main__": (options, args) = parser.parse_args() SetVerbose(options.verbose) - makewheel(options.version, options.outputdir) + makewheel(options.version, options.outputdir, options.platform) From ea2305de701fe89082bcd26de6b29d3077dc7a8b Mon Sep 17 00:00:00 2001 From: Sam Edwards Date: Mon, 26 Dec 2016 17:37:02 -0700 Subject: [PATCH 53/70] general: Fix missing includes. --- panda/src/gobj/shaderBuffer.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/panda/src/gobj/shaderBuffer.h b/panda/src/gobj/shaderBuffer.h index 5faa4322ac..549ebdc536 100644 --- a/panda/src/gobj/shaderBuffer.h +++ b/panda/src/gobj/shaderBuffer.h @@ -15,8 +15,11 @@ #define SHADERBUFFER_H #include "pandabase.h" +#include "typedWritableReferenceCount.h" #include "namable.h" #include "geomEnums.h" +#include "graphicsStateGuardianBase.h" +#include "factoryParams.h" class BufferContext; class PreparedGraphicsObjects; From cf105f276c55b7a02b87c527bc01f56ef3df306b Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 28 Dec 2016 20:23:27 +0100 Subject: [PATCH 54/70] More alignment fixes for 32-byte AVX --- dtool/src/dtoolbase/deletedBufferChain.cxx | 4 ++-- dtool/src/dtoolbase/dtoolbase.h | 5 +++++ panda/src/linmath/lsimpleMatrix.h | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/dtool/src/dtoolbase/deletedBufferChain.cxx b/dtool/src/dtoolbase/deletedBufferChain.cxx index 122edf8837..557b6ce9d8 100644 --- a/dtool/src/dtoolbase/deletedBufferChain.cxx +++ b/dtool/src/dtoolbase/deletedBufferChain.cxx @@ -71,7 +71,7 @@ allocate(size_t size, TypeHandle type_handle) { // Allocate memory, and make sure the object starts at the proper alignment. void *mem = NeverFreeMemory::alloc(alloc_size); - intptr_t pad = ((intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment(); + intptr_t pad = (-(intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment(); obj = (ObjectNode *)((uintptr_t)mem + pad); #ifdef USE_DELETEDCHAINFLAG @@ -80,7 +80,7 @@ allocate(size_t size, TypeHandle type_handle) { void *ptr = node_to_buffer(obj); -#ifdef _DEBUG +#ifndef NDEBUG assert(((uintptr_t)ptr % MemoryHook::get_memory_alignment()) == 0); #endif diff --git a/dtool/src/dtoolbase/dtoolbase.h b/dtool/src/dtoolbase/dtoolbase.h index b192f24055..c6cbbd7f46 100644 --- a/dtool/src/dtoolbase/dtoolbase.h +++ b/dtool/src/dtoolbase/dtoolbase.h @@ -339,21 +339,26 @@ typedef struct _object PyObject; #define ALIGN_4BYTE #define ALIGN_8BYTE #define ALIGN_16BYTE +#define ALIGN_32BYTE #define ALIGN_64BYTE #elif defined(_MSC_VER) #define ALIGN_4BYTE __declspec(align(4)) #define ALIGN_8BYTE __declspec(align(8)) #define ALIGN_16BYTE __declspec(align(16)) +#define ALIGN_32BYTE __declspec(align(32)) #define ALIGN_64BYTE __declspec(align(64)) #elif defined(__GNUC__) #define ALIGN_4BYTE __attribute__ ((aligned (4))) #define ALIGN_8BYTE __attribute__ ((aligned (8))) #define ALIGN_16BYTE __attribute__ ((aligned (16))) +#define ALIGN_32BYTE __attribute__ ((aligned (32))) #define ALIGN_64BYTE __attribute__ ((aligned (64))) #else #define ALIGN_4BYTE #define ALIGN_8BYTE #define ALIGN_16BYTE +#define ALIGN_32BYTE +#define ALIGN_64BYTE #endif // Do we need to implement memory-alignment enforcement within the MemoryHook diff --git a/panda/src/linmath/lsimpleMatrix.h b/panda/src/linmath/lsimpleMatrix.h index 0ba2dc1196..5669e18be3 100644 --- a/panda/src/linmath/lsimpleMatrix.h +++ b/panda/src/linmath/lsimpleMatrix.h @@ -58,7 +58,9 @@ private: #endif // HAVE_EIGEN // This is as good a place as any to define this alignment macro. -#ifdef LINMATH_ALIGN +#if defined(LINMATH_ALIGN) && defined(HAVE_EIGEN) && defined(__AVX__) +#define ALIGN_LINMATH ALIGN_32BYTE +#elif defined(LINMATH_ALIGN) #define ALIGN_LINMATH ALIGN_16BYTE #else #define ALIGN_LINMATH From fa851ae5acb2b0ce06a2ae425f896ce7acb983c4 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 4 Jan 2017 22:42:05 +0100 Subject: [PATCH 55/70] Allow custom version to be passed on to makewheel when building with --wheel --- makepanda/makepanda.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 95dc6d791b..c96d188bcb 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -52,6 +52,7 @@ RUNTIME=0 DISTRIBUTOR="" VERSION=None DEBVERSION=None +WHLVERSION=None RPMRELEASE="1" GIT_COMMIT=None P3DSUFFIX=None @@ -163,7 +164,7 @@ def usage(problem): def parseopts(args): global INSTALLER,WHEEL,RTDIST,RUNTIME,GENMAN,DISTRIBUTOR,VERSION global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL - global DEBVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION + global DEBVERSION,WHLVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION global STRDXSDKVERSION, WINDOWS_SDK, MSVC_VERSION, BOOUSEINTELCOMPILER longopts = [ "help","distributor=","verbose","runtime","osxtarget=", @@ -206,8 +207,11 @@ def parseopts(args): elif (option=="--arch"): target_arch = value.strip() elif (option=="--nocolor"): DisableColors() elif (option=="--version"): - VERSION=value - if (len(VERSION.split(".")) != 3): raise Exception + match = re.match(r'^\d+\.\d+\.\d+', value) + if not match: + usage("version requires three digits") + WHLVERSION = value + VERSION = match.group() elif (option=="--lzma"): COMPRESSOR="lzma" elif (option=="--override"): AddOverride(value.strip()) elif (option=="--static"): SetLinkAllStatic(True) @@ -7257,7 +7261,7 @@ try: if WHEEL: ProgressOutput(100.0, "Building wheel") from makewheel import makewheel - makewheel(VERSION, GetOutputDir()) + makewheel(WHLVERSION, GetOutputDir()) finally: SaveDependencyCache() From 40ea0ab7869a77093d4d60fe31f01fcf58d60089 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 4 Jan 2017 22:46:57 +0100 Subject: [PATCH 56/70] cppparser: support directives __LINE__, __FILE__, __has_include --- dtool/src/cppparser/cppPreprocessor.cxx | 247 +++++++++++++++++------- dtool/src/cppparser/cppPreprocessor.h | 3 + 2 files changed, 177 insertions(+), 73 deletions(-) diff --git a/dtool/src/cppparser/cppPreprocessor.cxx b/dtool/src/cppparser/cppPreprocessor.cxx index 83050d3c41..feda153530 100644 --- a/dtool/src/cppparser/cppPreprocessor.cxx +++ b/dtool/src/cppparser/cppPreprocessor.cxx @@ -809,6 +809,8 @@ expand_manifests(const string &input_expr, bool expand_undefined, // Here's an identifier. Is it "defined"? if (ident == "defined") { expand_defined_function(expr, q, p); + } else if (expand_undefined && ident == "__has_include") { + expand_has_include_function(expr, q, p, loc); } else { // Is it a manifest? Manifests::const_iterator mi = _manifests.find(ident); @@ -817,6 +819,20 @@ expand_manifests(const string &input_expr, bool expand_undefined, expand_manifest_inline(expr, q, p, manifest); manifest_found = true; + } else if (ident == "__FILE__") { + // Special case: this is a dynamic definition. + string file = string("\"") + loc.file._filename_as_referenced.get_fullpath() + "\""; + expr = expr.substr(0, q) + file + expr.substr(p); + p = q + file.size(); + manifest_found = true; + + } else if (ident == "__LINE__") { + // So is this. + string line = format_string(loc.first_line); + expr = expr.substr(0, q) + line + expr.substr(p); + p = q + line.size(); + manifest_found = true; + } else if (expand_undefined && ident != "true" && ident != "false") { // It is not found. Expand it to 0, but only if we are currently // parsing an #if expression. @@ -1486,14 +1502,10 @@ handle_undef_directive(const string &args, const YYLTYPE &loc) { */ void CPPPreprocessor:: handle_ifdef_directive(const string &args, const YYLTYPE &loc) { - Manifests::const_iterator mi = _manifests.find(args); - if (mi != _manifests.end()) { - // The macro is defined. We continue. - return; + if (!is_manifest_defined(args)) { + // The macro is undefined. Skip stuff. + skip_false_if_block(true); } - - // The macro is undefined. Skip stuff. - skip_false_if_block(true); } /** @@ -1501,17 +1513,12 @@ handle_ifdef_directive(const string &args, const YYLTYPE &loc) { */ void CPPPreprocessor:: handle_ifndef_directive(const string &args, const YYLTYPE &loc) { - Manifests::const_iterator mi = _manifests.find(args); - if (mi == _manifests.end()) { - // The macro is undefined. We continue. - return; + if (is_manifest_defined(args)) { + // The macro is defined. Skip stuff. + skip_false_if_block(true); } - - // The macro is defined. Skip stuff. - skip_false_if_block(true); } - /** * */ @@ -1593,6 +1600,8 @@ handle_include_directive(const string &args, const YYLTYPE &loc) { _angle_includes.insert(filename); } } + } else { + warning("Ignoring invalid #include directive", loc); } filename.set_text(); @@ -1600,71 +1609,30 @@ handle_include_directive(const string &args, const YYLTYPE &loc) { // Now look for the filename. If we didn't use angle quotes, look first in // the current directory. - bool found_file = false; CPPFile::Source source = CPPFile::S_none; - if (okflag) { - found_file = false; + if (find_include(filename, angle_quotes, source)) { + _last_c = '\0'; - // Search the current directory. - if (!angle_quotes && !found_file && filename.exists()) { - found_file = true; + // If it was explicitly named on the command-line, mark it S_local. + filename.make_canonical(); + if (_explicit_files.count(filename)) { source = CPPFile::S_local; } - // Search the same directory as the includer. - if (!angle_quotes && !found_file) { - Filename match(get_file()._filename.get_dirname(), filename); - if (match.exists()) { - filename = match; - found_file = true; - source = CPPFile::S_alternate; - } + CPPFile file(filename, filename_as_referenced, source); + + // Don't include it if we included it before and it had #pragma once. + ParsedFiles::const_iterator it = _parsed_files.find(file); + if (it != _parsed_files.end() && it->_pragma_once) { + return; } - // Now search the angle-include-path - if (angle_quotes && !found_file && filename.resolve_filename(_angle_include_path)) { - found_file = true; - source = CPPFile::S_system; - } - - // Now search the quote-include-path - if (!angle_quotes && !found_file) { - for (size_t dir=0; dir<_quote_include_path.get_num_directories(); dir++) { - Filename match(_quote_include_path.get_directory(dir), filename); - if (match.exists()) { - filename = match; - found_file = true; - source = _quote_include_kind[dir]; - } - } - } - - if (!found_file) { - warning("Cannot find " + filename.get_fullpath(), loc); - } else { - _last_c = '\0'; - - // If it was explicitly named on the command-line, mark it S_local. - filename.make_canonical(); - if (_explicit_files.count(filename)) { - source = CPPFile::S_local; - } - - CPPFile file(filename, filename_as_referenced, source); - - // Don't include it if we included it before and it had #pragma once. - ParsedFiles::const_iterator it = _parsed_files.find(file); - if (it != _parsed_files.end() && it->_pragma_once) { - return; - } - - if (!push_file(file)) { - warning("Unable to read " + filename.get_fullpath(), loc); - } + if (!push_file(file)) { + warning("Unable to read " + filename.get_fullpath(), loc); } } else { - warning("Ignoring invalid #include directive", loc); + warning("Cannot find " + filename.get_fullpath(), loc); } } @@ -1779,6 +1747,69 @@ skip_false_if_block(bool consider_elifs) { _save_comments = true; } +/** + * Returns true if the given manifest is defined. + */ +bool CPPPreprocessor:: +is_manifest_defined(const string &manifest_name) { + Manifests::const_iterator mi = _manifests.find(manifest_name); + if (mi != _manifests.end()) { + return true; + } + + if (manifest_name == "__has_include" || + manifest_name == "__FILE__" || + manifest_name == "__LINE__") { + // Special built-in directives that are considered "defined". + return true; + } + + return false; +} + +/** + * Locates the given filename. Changes the first argument to the full path. + */ +bool CPPPreprocessor:: +find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source) { + // Now look for the filename. If we didn't use angle quotes, look first in + // the current directory. + if (!angle_quotes && filename.exists()) { + source = CPPFile::S_local; + return true; + } + + // Search the same directory as the includer. + if (!angle_quotes) { + Filename match(get_file()._filename.get_dirname(), filename); + if (match.exists()) { + filename = match; + source = CPPFile::S_alternate; + return true; + } + } + + // Now search the angle-include-path + if (angle_quotes && filename.resolve_filename(_angle_include_path)) { + source = CPPFile::S_system; + return true; + } + + // Now search the quote-include-path + if (!angle_quotes) { + for (size_t dir = 0; dir < _quote_include_path.get_num_directories(); ++dir) { + Filename match(_quote_include_path.get_directory(dir), filename); + if (match.exists()) { + filename = match; + source = _quote_include_kind[dir]; + return true; + } + } + } + + return false; +} + /** * */ @@ -1885,6 +1916,14 @@ get_identifier(int c) { if (mi != _manifests.end() && !should_ignore_manifest((*mi).second)) { return expand_manifest((*mi).second); } + if (name == "__FILE__") { + return get_literal(SIMPLE_STRING, loc, loc.file._filename_as_referenced); + } + if (name == "__LINE__") { + YYSTYPE result; + result.u.integer = loc.first_line; + return CPPToken(INTEGER, loc, "", result); + } // Check for keywords. int kw = check_keyword(name); @@ -2227,9 +2266,7 @@ expand_defined_function(string &expr, size_t q, size_t &p) { vector_string args; extract_manifest_args_inline("defined", 1, -1, args, expr, p); if (args.size() >= 1) { - const string &manifest_name = args[0]; - Manifests::const_iterator mi = _manifests.find(manifest_name); - if (mi != _manifests.end()) { + if (is_manifest_defined(args[0])) { // The macro is defined; the result is "1". result = "1"; } else { @@ -2242,6 +2279,70 @@ expand_defined_function(string &expr, size_t q, size_t &p) { p = q + result.size(); } +/** + * Expands the __has_include(manifest) function to either 1 or 0, depending on + * whether the include file exists. + */ +void CPPPreprocessor:: +expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc) { + bool found_file = false; + + // Skip whitespace till paren. + while (p < expr.size() && isspace(expr[p])) { + p++; + } + size_t args_begin = p + 1; + + vector_string args; + extract_manifest_args_inline("__has_include", 1, -1, args, expr, p); + + if (!args.empty() && args[0].size() >= 2) { + Filename filename; + bool angle_quotes = false; + + string inc = args[0]; + + // Just to play things safe, since our manifest-expansion logic might not + // filter out quotes and angle brackets properly, we'll only expand + // manifests if we don't begin with a quote or bracket. + if (!inc.empty() && (inc[0] != '"' && inc[0] != '<')) { + inc = expand_manifests(inc, false, loc); + } + + if (inc[0] == '"' && inc[inc.size() - 1] == '"') { + filename = inc.substr(1, inc.size() - 2); + } else if (inc[0] == '<' && inc[inc.size() - 1] == '>') { + filename = inc.substr(1, inc.size() - 2); + if (!_noangles) { + // If _noangles is true, we don't make a distinction between angle + // brackets and quote marks--all #inc statements are treated the + // same, as if they used quote marks. + angle_quotes = true; + } + } else { + loc.last_column += loc.first_column + p - 2; + loc.first_column += args_begin; + warning("invalid argument for __has_include() directive", loc); + expr = expr.substr(0, q) + "0" + expr.substr(p); + p = q + 1; + return; + } + + filename.set_text(); + + CPPFile::Source source = CPPFile::S_none; + found_file = find_include(filename, angle_quotes, source); + } else { + loc.last_column += loc.first_column + p - 2; + loc.first_column += args_begin; + warning("invalid argument for __has_include() directive", loc); + } + + string result = found_file ? "1" : "0"; + expr = expr.substr(0, q) + result + expr.substr(p); + p = q + result.size(); +} + /** * */ diff --git a/dtool/src/cppparser/cppPreprocessor.h b/dtool/src/cppparser/cppPreprocessor.h index e375b259dd..e119211596 100644 --- a/dtool/src/cppparser/cppPreprocessor.h +++ b/dtool/src/cppparser/cppPreprocessor.h @@ -143,6 +143,8 @@ private: void handle_error_directive(const string &args, const YYLTYPE &loc); void skip_false_if_block(bool consider_elifs); + bool is_manifest_defined(const string &manifest_name); + bool find_include(Filename &filename, bool angle_quotes, CPPFile::Source &source); CPPToken get_quoted_char(int c); CPPToken get_quoted_string(int c); @@ -153,6 +155,7 @@ private: void extract_manifest_args(const string &name, int num_args, int va_arg, vector_string &args); void expand_defined_function(string &expr, size_t q, size_t &p); + void expand_has_include_function(string &expr, size_t q, size_t &p, YYLTYPE loc); void expand_manifest_inline(string &expr, size_t q, size_t &p, const CPPManifest *manifest); void extract_manifest_args_inline(const string &name, int num_args, From 40e981e485c383367d5f2a9bacf2b906ea90df2d Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 4 Jan 2017 22:47:58 +0100 Subject: [PATCH 57/70] makepanda: enable C++11 support by default --- makepanda/makepanda.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index c96d188bcb..92f7edb5f7 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1194,7 +1194,7 @@ def CompileCxx(obj,src,opts): if (COMPILER=="GCC"): if (src.endswith(".c")): cmd = GetCC() +' -fPIC -c -o ' + obj - else: cmd = GetCXX()+' -ftemplate-depth-70 -fPIC -c -o ' + obj + else: cmd = GetCXX()+' -std=gnu++0x -ftemplate-depth-70 -fPIC -c -o ' + obj for (opt, dir) in INCDIRECTORIES: if (opt=="ALWAYS") or (opt in opts): cmd += ' -I' + BracketNameWithQuotes(dir) for (opt, dir) in FRAMEWORKDIRECTORIES: From 9facf874aba9b2b051b8cd1f0e62bb8baf68cda3 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 4 Jan 2017 23:53:24 +0100 Subject: [PATCH 58/70] Let compiler synthesize QuadDef move assignment operator This hopefully fixes a compile issue with older clang versions. --- panda/src/text/textAssembler.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/panda/src/text/textAssembler.h b/panda/src/text/textAssembler.h index 1215765bf5..64b4c7ef03 100644 --- a/panda/src/text/textAssembler.h +++ b/panda/src/text/textAssembler.h @@ -212,21 +212,6 @@ private: typedef pmap GeomCollectorMap; struct QuadDef { - // Copying this class is a performance hotspot, hence we define the move - // constructor. - ALWAYS_INLINE QuadDef() {} - ALWAYS_INLINE QuadDef(const QuadDef ©) : - _dimensions(copy._dimensions), _uvs(copy._uvs), - _slantl(copy._slantl), _slanth(copy._slanth), - _glyph(copy._glyph) {} - -#ifdef USE_MOVE_SEMANTICS - ALWAYS_INLINE QuadDef(QuadDef &&from) NOEXCEPT : - _dimensions(from._dimensions), _uvs(from._uvs), - _slantl(from._slantl), _slanth(from._slanth), - _glyph(move(from._glyph)) {} -#endif - LVecBase4 _dimensions; LVecBase4 _uvs; PN_stdfloat _slantl, _slanth; From 603f0eb3b18b72b8fe85b6710c8c63fbb80330c8 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 4 Jan 2017 16:28:38 -0800 Subject: [PATCH 59/70] fix occasional crash in PNMImage::quick_filter_from() --- panda/src/pnmimage/pnm-image-filter.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/panda/src/pnmimage/pnm-image-filter.cxx b/panda/src/pnmimage/pnm-image-filter.cxx index ac57b20b23..63398ad3c1 100644 --- a/panda/src/pnmimage/pnm-image-filter.cxx +++ b/panda/src/pnmimage/pnm-image-filter.cxx @@ -696,7 +696,7 @@ box_filter_line(const PNMImage &image, // Get the final (partial) xel float x_contrib = x1 - (float)x_last; - if (x_contrib > 0.0001f) { + if (x_contrib > 0.0001f && x < image.get_x_size()) { box_filter_xel(image, x, y, x_contrib, y_contrib, color, pixel_count); } @@ -728,7 +728,7 @@ box_filter_region(const PNMImage &image, // Get the final (partial) row float y_contrib = y1 - (float)y_last; - if (y_contrib > 0.0001f) { + if (y_contrib > 0.0001f && y < image.get_y_size()) { box_filter_line(image, x0, y, x1, y_contrib, color, pixel_count); } From c4d232b0be9de4e64fd067d8deb3ebe7953b0da5 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 4 Jan 2017 16:56:09 -0800 Subject: [PATCH 60/70] publish PfmVizzer destructor to fix leak --- panda/src/grutil/pfmVizzer.I | 4 ++++ panda/src/grutil/pfmVizzer.h | 1 + 2 files changed, 5 insertions(+) diff --git a/panda/src/grutil/pfmVizzer.I b/panda/src/grutil/pfmVizzer.I index 6a0a5a23bc..2185248829 100644 --- a/panda/src/grutil/pfmVizzer.I +++ b/panda/src/grutil/pfmVizzer.I @@ -19,6 +19,10 @@ get_pfm() { return _pfm; } +INLINE PfmVizzer:: +~PfmVizzer() { +} + /** * Returns the reference to the PfmFile manipulated by this PfmVizzer. */ diff --git a/panda/src/grutil/pfmVizzer.h b/panda/src/grutil/pfmVizzer.h index 7b466f0ee3..e8423f8dd1 100644 --- a/panda/src/grutil/pfmVizzer.h +++ b/panda/src/grutil/pfmVizzer.h @@ -30,6 +30,7 @@ class GeomVertexWriter; class EXPCL_PANDA_GRUTIL PfmVizzer { PUBLISHED: PfmVizzer(PfmFile &pfm); + INLINE ~PfmVizzer(); INLINE PfmFile &get_pfm(); INLINE const PfmFile &get_pfm() const; From 127cbc3b3840dace259d092353a3251aa8942693 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 5 Jan 2017 17:15:42 +0100 Subject: [PATCH 61/70] Windows installer improvements and fixes: - copy .ico file - write installer log to install.log - restore python DLL to bin directory --- makepanda/installer.nsi | 70 +++++++++++++++++++++++++++++++++++------ makepanda/makepanda.py | 17 +++++----- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/makepanda/installer.nsi b/makepanda/installer.nsi index d934cc4ee0..d004d15006 100755 --- a/makepanda/installer.nsi +++ b/makepanda/installer.nsi @@ -141,8 +141,9 @@ SectionGroup "Panda3D Libraries" SetDetailsPrint listonly SetOutPath "$INSTDIR" - File "${BUILT}\LICENSE" - File /r /x CVS "${BUILT}\ReleaseNotes" + File /nonfatal "${BUILT}\LICENSE" + File /nonfatal "${BUILT}\ReleaseNotes" + File /nonfatal "${BUILT}\pandaIcon.ico" SetOutPath $INSTDIR\etc File /r "${BUILT}\etc\*" @@ -532,15 +533,17 @@ Section "Sample programs" SecSamples WriteINIStr $INSTDIR\Manual.url "InternetShortcut" "URL" "https://www.panda3d.org/manual/index.php" WriteINIStr $INSTDIR\Samples.url "InternetShortcut" "URL" "https://www.panda3d.org/manual/index.php/Sample_Programs_in_the_Distribution" SetOutPath $INSTDIR - CreateShortCut "$SMPROGRAMS\${TITLE}\Panda3D Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda3D Manual" - CreateShortCut "$SMPROGRAMS\${TITLE}\Panda3D Website.lnk" "$INSTDIR\Website.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda3D Website" - CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Program Manual.lnk" "$INSTDIR\Samples.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Sample Program Manual" + CreateShortCut "$SMPROGRAMS\${TITLE}\Panda3D Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\pandaIcon.ico" 0 "" "" "Panda3D Manual" + CreateShortCut "$SMPROGRAMS\${TITLE}\Panda3D Website.lnk" "$INSTDIR\Website.url" "" "$INSTDIR\pandaIcon.ico" 0 "" "" "Panda3D Website" + CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Program Manual.lnk" "$INSTDIR\Samples.url" "" "$INSTDIR\pandaIcon.ico" 0 "" "" "Sample Program Manual" FindFirst $0 $1 $INSTDIR\samples\* loop: StrCmp $1 "" done StrCmp $1 "." next StrCmp $1 ".." next + FindFirst $2 $3 $INSTDIR\samples\$1\*.py + StrCmp $3 "" next Push $1 Push "-" Push " " @@ -557,14 +560,13 @@ Section "Sample programs" SecSamples DetailPrint "Creating shortcuts for sample program $READABLE" CreateDirectory "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE" SetOutPath $INSTDIR\samples\$1 - WriteINIStr $INSTDIR\samples\$1\ManualPage.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs:_$MANPAGE" - CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\Manual Page.lnk" "$INSTDIR\samples\$1\ManualPage.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Manual Entry on this Sample Program" + WriteINIStr $INSTDIR\samples\$1\ManualPage.url "InternetShortcut" "URL" "https://www.panda3d.org/wiki/index.php/Sample_Programs:_$MANPAGE" + CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\Manual Page.lnk" "$INSTDIR\samples\$1\ManualPage.url" "" "$INSTDIR\pandaIcon.ico" 0 "" "" "Manual Entry on this Sample Program" CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\View Source Code.lnk" "$INSTDIR\samples\$1" - FindFirst $2 $3 $INSTDIR\samples\$1\*.py iloop: StrCmp $3 "" idone - CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\Run $3.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $3" - CreateShortCut "$INSTDIR\samples\$1\Run $3.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $3" + CreateShortCut "$SMPROGRAMS\${TITLE}\Sample Programs\$READABLE\Run $3.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\pandaIcon.ico" 0 SW_SHOWMINIMIZED "" "Run $3" + CreateShortCut "$INSTDIR\samples\$1\Run $3.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\pandaIcon.ico" 0 SW_SHOWMINIMIZED "" "Run $3" FindNext $2 $3 goto iloop idone: @@ -684,6 +686,10 @@ Section -post DetailPrint "Broadcasting WM_WININICHANGE message..." SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=500 + # Now dump the log to disk. + StrCpy $0 "$INSTDIR\install.log" + Push $0 + Call DumpLog SectionEnd Section Uninstall @@ -1235,3 +1241,47 @@ done: Exch $R3 FunctionEnd + +!define LVM_GETITEMCOUNT 0x1004 +!define LVM_GETITEMTEXT 0x102D + +Function DumpLog + Exch $5 + Push $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $6 + + FindWindow $0 "#32770" "" $HWNDPARENT + GetDlgItem $0 $0 1016 + StrCmp $0 0 exit + FileOpen $5 $5 "w" + StrCmp $5 "" exit + SendMessage $0 ${LVM_GETITEMCOUNT} 0 0 $6 + System::Alloc ${NSIS_MAX_STRLEN} + Pop $3 + StrCpy $2 0 + System::Call "*(i, i, i, i, i, i, i, i, i) i \ + (0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1" + loop: StrCmp $2 $6 done + System::Call "User32::SendMessageA(i, i, i, i) i \ + ($0, ${LVM_GETITEMTEXT}, $2, r1)" + System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)" + FileWrite $5 "$4$\r$\n" + IntOp $2 $2 + 1 + Goto loop + done: + FileClose $5 + System::Free $1 + System::Free $3 + exit: + Pop $6 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 + Exch $5 +FunctionEnd diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 92f7edb5f7..2e54cc2058 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2871,11 +2871,13 @@ if tp_dir is not None: CopyAllFiles(GetOutputDir() + "/bin/", tp_dir + "extras/bin/") if not PkgSkip("PYTHON") and not RTDIST: - #XXX rdb I don't think we need to copy over the Python DLL, do we? - #pydll = "/" + SDK["PYTHONVERSION"].replace(".", "") - #if (GetOptimize() <= 2): pydll += "_d.dll" - #else: pydll += ".dll" - #CopyFile(GetOutputDir() + "/bin" + pydll, SDK["PYTHON"] + pydll) + # We need to copy the Python DLL to the bin directory for now. + pydll = "/" + SDK["PYTHONVERSION"].replace(".", "") + if GetOptimize() <= 2: + pydll += "_d.dll" + else: + pydll += ".dll" + CopyFile(GetOutputDir() + "/bin" + pydll, SDK["PYTHON"] + pydll) #for fn in glob.glob(SDK["PYTHON"] + "/vcruntime*.dll"): # CopyFile(GetOutputDir() + "/bin/", fn) @@ -2949,6 +2951,7 @@ if GetTarget() == 'windows': # Convert to Windows newlines so they can be opened by notepad. WriteFile(GetOutputDir() + "/LICENSE", ReadFile("doc/LICENSE"), newline='\r\n') WriteFile(GetOutputDir() + "/ReleaseNotes", ReadFile("doc/ReleaseNotes"), newline='\r\n') + CopyFile(GetOutputDir() + "/pandaIcon.ico", "panda/src/configfiles/pandaIcon.ico") else: CopyFile(GetOutputDir()+"/", "doc/LICENSE") CopyFile(GetOutputDir()+"/", "doc/ReleaseNotes") @@ -6596,7 +6599,7 @@ def MakeInstallerNSIS(file, title, installdir): AddToPathEnv("PATH", GetOutputDir() + "\\bin") AddToPathEnv("PATH", GetOutputDir() + "\\plugins") - cmd = sys.executable + " -B -u direct\\src\\plugin_installer\\make_installer.py" + cmd = sys.executable + " -B -u " + os.path.join("direct", "src", "plugin_installer", "make_installer.py") cmd += " --version %s --regview %s" % (VERSION, regview) if GetTargetArch() == 'x64': @@ -6605,7 +6608,7 @@ def MakeInstallerNSIS(file, title, installdir): cmd += " --install \"$PROGRAMFILES32\\Panda3D\" " oscmd(cmd) - shutil.move("direct\\src\\plugin_installer\\p3d-setup.exe", file) + shutil.move(os.path.join("direct", "src", "plugin_installer", "p3d-setup.exe"), file) return print("Building "+title+" installer at %s" % (file)) From 53752bd3762cd9dbe9d7ba38c14594ff058367b2 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 5 Jan 2017 17:22:11 +0100 Subject: [PATCH 62/70] Remove packpanda and eggcacher, don't require libpython on Linux --- direct/src/directbase/ppython.cxx | 106 ---- direct/src/directscripts/eggcacher.py | 11 +- direct/src/directscripts/packpanda.nsi | 831 ------------------------- direct/src/directscripts/packpanda.py | 424 ------------- makepanda/installer.nsi | 9 +- makepanda/makepanda.py | 22 +- makepanda/makepandacore.py | 2 +- makepanda/makewheel.py | 1 - 8 files changed, 20 insertions(+), 1386 deletions(-) delete mode 100644 direct/src/directbase/ppython.cxx delete mode 100755 direct/src/directscripts/packpanda.nsi delete mode 100755 direct/src/directscripts/packpanda.py diff --git a/direct/src/directbase/ppython.cxx b/direct/src/directbase/ppython.cxx deleted file mode 100644 index e460de766c..0000000000 --- a/direct/src/directbase/ppython.cxx +++ /dev/null @@ -1,106 +0,0 @@ -// This is a little wrapper to make it easy to run a python program from the -// command line. Basically, it just interfaces to the Python API and imports -// the module that was specified by the IMPORT_MODULE preprocessor definition -// when it was compiled. - -#include "dtoolbase.h" - -#undef _POSIX_C_SOURCE -#undef _XOPEN_SOURCE -#include -#if PY_MAJOR_VERSION >= 3 -#include -#endif - -#ifndef IMPORT_MODULE -#error IMPORT_MODULE must be defined when compiling ppython.cxx ! -#endif - -#define _STRINGIFY(s) #s -#define STRINGIFY(s) _STRINGIFY(s) -#define IMPORT_MODULE_STR STRINGIFY(IMPORT_MODULE) - -#if defined(_WIN32) && PY_MAJOR_VERSION >= 3 -// As Py_SetProgramName expects a wchar_t*, it's easiest to just use the wmain -// entry point. -int wmain(int argc, wchar_t *argv[]) { - Py_SetProgramName(argv[0]); - -#elif PY_MAJOR_VERSION >= 3 -// Convert from UTF-8 to wchar_t*. -int main(int argc, char *mb_argv[]) { - wchar_t **argv = new wchar_t*[argc + 1]; - for (int i = 0; i < argc; ++i) { - size_t len = mbstowcs(NULL, mb_argv[i], 0); - argv[i] = new wchar_t[len + 1]; - mbstowcs(argv[i], mb_argv[i], len); - argv[i][len] = 0; - } - // Just for good measure - argv[argc] = NULL; - - Py_SetProgramName(argv[0]); - -#else -// Python 2. -int main(int argc, char *argv[]) { - Py_SetProgramName(argv[0]); -#endif - - // On Windows, we need to set pythonhome correctly. We'll try to find - // ppython.exe on the path and set pythonhome to its location. -#ifdef _WIN32 -#if PY_MAJOR_VERSION >= 3 - // Py_SetPythonHome expects a wchar_t in Python 3. - wchar_t *path = _wgetenv(L"PATH"); - wchar_t *result = wcstok(path, L";"); - while (result != NULL) { - struct _stat st; - wchar_t *ppython = (wchar_t*) malloc(wcslen(result) * 2 + 26); - wcscpy(ppython, result); - wcscat(ppython, L"\\python.exe"); - if (_wstat(ppython, &st) == 0) { - Py_SetPythonHome(result); - free(ppython); - break; - } - result = wcstok(NULL, L";"); - free(ppython); - } -#else - char *path = getenv("PATH"); - char *result = strtok(path, ";"); - while (result != NULL) { - struct stat st; - char *ppython = (char*) malloc(strlen(result) + 13); - strcpy(ppython, result); - strcat(ppython, "\\ppython.exe"); - if (stat(ppython, &st) == 0) { - Py_SetPythonHome(result); - free(ppython); - break; - } - result = strtok(NULL, ";"); - free(ppython); - } -#endif -#endif - - Py_Initialize(); - - if (Py_VerboseFlag) { - fprintf(stderr, "Python %s\\n%s\\n", Py_GetVersion(), Py_GetCopyright()); - } - - PySys_SetArgv(argc, argv); - - int sts = 0; - PyObject* m = PyImport_ImportModule(IMPORT_MODULE_STR); - if (m <= 0) { - PyErr_Print(); - sts = 1; - } - - Py_Finalize(); - return sts; -} diff --git a/direct/src/directscripts/eggcacher.py b/direct/src/directscripts/eggcacher.py index ad11303fe0..6dcee8e2d3 100644 --- a/direct/src/directscripts/eggcacher.py +++ b/direct/src/directscripts/eggcacher.py @@ -87,8 +87,13 @@ class EggCacher: TexturePool.releaseAllTextures() progress += size -cacher = EggCacher(sys.argv[1:]) -# Dummy main function so this can be added to console_scripts. -def main(): +def main(args=None): + if args is None: + args = sys.argv[1:] + + cacher = EggCacher(args) return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/direct/src/directscripts/packpanda.nsi b/direct/src/directscripts/packpanda.nsi deleted file mode 100755 index 73c9011d9a..0000000000 --- a/direct/src/directscripts/packpanda.nsi +++ /dev/null @@ -1,831 +0,0 @@ -; Panda3D installation script for the Nullsoft Installation System (NSIS). -; Jon Parise -; with Ben Johnson -; with Jason Pratt -; mangled by Josh Yelon - -; Caller needs to define these variables: -; -; COMPRESSOR - either zlib or lzma -; NAME - name of what we're building (ie, "Panda3D" or "Airblade") -; SMDIRECTORY - where to put this in the start menu (ie, "Panda3D 1.1.0" or "Airblade 1.1.0") -; INSTALLDIR - where to install the program (ie, "C:\Program Files\Panda3D-1.1.0") -; OUTFILE - where to put the output file (ie, "..\nsis-output.exe") -; LICENSE - location of the license file (ie, "C:\Airblade\LICENSE.TXT") -; LANGUAGE - name of the Language file to use (ie, "English" or "Panda3DEnglish") -; RUNTEXT - text for run-box at end of installation (ie, "Run the Panda Greeting Card") -; IBITMAP - name of installer bitmap (ie, "C:\Airblade\Airblade.bmp") -; UBITMAP - name of uninstaller bitmap (ie, "C:\Airblade\Airblade.bmp") -; -; PANDA - location of panda install tree. -; PYVER - version of Python that Panda was built with (ie, "2.7") -; PANDACONF - name of panda config directory - usually $PANDA\etc -; PSOURCE - location of the panda source-tree if available, OR location of panda install tree. -; PYEXTRAS - directory containing python extras, if any. -; REGVIEW - either 32 or 64, depending on the build architecture. -; -; PPGAME - directory containing prepagaged game, if any (ie, "C:\My Games\Airblade") -; PPMAIN - python program containing prepackaged game, if any (ie, "Airblade.py") -; PPICON - file containing icon of prepackaged game. -; - -!include "MUI.nsh" -!include "WinMessages.nsh" -Name "${NAME}" -InstallDir "${INSTALLDIR}" -OutFile "${OUTFILE}" - -SetCompress auto -SetCompressor ${COMPRESSOR} - -!define MUI_WELCOMEFINISHPAGE_BITMAP "${IBITMAP}" -!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${UBITMAP}" - -!define MUI_ABORTWARNING -!define MUI_FINISHPAGE_NOREBOOTSUPPORT -!define MUI_FINISHPAGE_RUN -!define MUI_FINISHPAGE_RUN_FUNCTION runFunction -!define MUI_FINISHPAGE_RUN_TEXT "${RUNTEXT}" - -!insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_LICENSE "${LICENSE}" -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_PAGE_FINISH - -!insertmacro MUI_UNPAGE_WELCOME -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES -!insertmacro MUI_UNPAGE_FINISH - -!insertmacro MUI_LANGUAGE "${LANGUAGE}" - -ShowInstDetails nevershow -ShowUninstDetails nevershow - -LicenseData "${LICENSE}" - -InstType "Typical" - -!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS - -var READABLE -var MANPAGE -var TUTNAME - -Function runFunction - !ifdef PPGAME - ExecShell "open" "$SMPROGRAMS\${SMDIRECTORY}\Play ${NAME}.lnk" - !else - ExecShell "open" "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk" - !endif -FunctionEnd - -Section "${SMDIRECTORY}" SecCore - SectionIn 1 2 3 RO - - SetDetailsPrint none - SetOutPath $INSTDIR - SetOverwrite try - - SetOutPath $INSTDIR - File "${PANDA}\LICENSE" - SetOutPath $INSTDIR\bin - File /r "${PANDA}\bin\*.dll" - File /nonfatal /r "${PANDA}\bin\*.pyd" - File /nonfatal /r "${PANDA}\bin\Microsoft.*.manifest" - SetOutPath $INSTDIR\etc - File /r "${PANDACONF}\*" - SetOutPath $INSTDIR\direct\directscripts - File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\directscripts\*" - SetOutPath $INSTDIR\direct\filter - File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\filter\*.sha" - SetOutPath $INSTDIR\direct - File /r /x CVS /x Opt?-Win32 "${PANDA}\direct\*.py" - Delete "$INSTDIR\panda3d.py" - Delete "$INSTDIR\panda3d.pyc" - Delete "$INSTDIR\panda3d.pyo" - SetOutPath $INSTDIR\pandac - File /r "${PANDA}\pandac\*.py" - SetOutPath $INSTDIR\panda3d - File /r "${PANDA}\panda3d\*.py" - File /r "${PANDA}\panda3d\*.pyd" - SetOutPath $INSTDIR\python - File /r "${PANDA}\python\*" - RMDir /r "$SMPROGRAMS\${SMDIRECTORY}" - CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}" - - !ifdef PPGAME - - SetOutPath $INSTDIR\models - File /r /x CVS "${PANDA}\models\*" - SetOutPath $INSTDIR\bin - File /r "${PANDA}\bin\eggcacher.exe" - SetOutpath $INSTDIR\game - File /r "${PPGAME}\*" - CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Play ${NAME}.lnk" "$INSTDIR\python\ppython.exe" "-E ${PPMAIN}" "$INSTDIR\${PPICON}" 0 SW_SHOWMINIMIZED "" "Play ${NAME}" - # Preload all EGG files into the model-cache - SetOutPath $INSTDIR - SetDetailsPrint textonly - SetDetailsView show - nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise game' - SetDetailsPrint none - SetDetailsView hide - - !else - - SetOutPath $INSTDIR\plugins - File /nonfatal /r "${PANDA}\plugins\*.dle" - File /nonfatal /r "${PANDA}\plugins\*.dlo" - File /nonfatal /r "${PANDA}\plugins\*.mll" - File /nonfatal /r "${PANDA}\plugins\*.mel" - File /nonfatal /r "${PANDA}\plugins\*.ms" - File "${PSOURCE}\doc\INSTALLING-PLUGINS.TXT" - SetOutPath $INSTDIR\pandac\input - File /r "${PANDA}\pandac\input\*" - SetOutPath $INSTDIR\bin - File /r "${PANDA}\bin\*.exe" - File /nonfatal /r "${PANDA}\bin\*.p3d" - SetOutPath $INSTDIR\lib - File /r /x *.exp "${PANDA}\lib\*" - SetOutPath $INSTDIR\include - File /r /x *.exp "${PANDA}\include\*" - SetOutPath $INSTDIR\Pmw - File /r /x CVS "${PANDA}\Pmw\*" - SetOutPath $INSTDIR\NSIS - File /r /x CVS "${NSISDIR}\*" - SetOutPath $INSTDIR - File /r /x CVS "${PANDA}\ReleaseNotes" - !ifdef PYEXTRAS - SetOutPath $INSTDIR\python\lib - File /nonfatal /r "${PYEXTRAS}\*" - !endif - SetOutPath $INSTDIR\models - File /r /x CVS "${PANDA}\models\*" - SetOutPath $INSTDIR\samples - File /nonfatal /r /x CVS "${PSOURCE}\samples\*" - MessageBox MB_YESNO|MB_ICONQUESTION \ - "EGG caching is about to begin.$\nThis process may take a couple minute and approximately 270 MB of RAM.$\nWARNING : It might stuck if your computer resources are low.$\n$\nDo you really want to do this optional step ?" \ - IDNO SkipCaching - # Preload all EGG files into the model-cache - SetOutPath $INSTDIR - SetDetailsPrint both - SetDetailsView show - nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise models samples' - SetDetailsPrint none - SetDetailsView hide - SkipCaching: - - SetOutPath $INSTDIR - WriteINIStr $INSTDIR\Website.url "InternetShortcut" "URL" "http://panda3d.org/" - WriteINIStr $INSTDIR\Manual.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php" - WriteINIStr $INSTDIR\Samples.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs_in_the_Distribution" - SetOutPath $INSTDIR - CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Manual.lnk" "$INSTDIR\Manual.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda Manual" - CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Panda Website.lnk" "$INSTDIR\Website.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Panda Website" - CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Program Manual.lnk" "$INSTDIR\Samples.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Sample Program Manual" - - FindFirst $0 $1 $INSTDIR\samples\* - loop: - StrCmp $1 "" done - StrCmp $1 "." next - StrCmp $1 ".." next - Push $1 - Push "-" - Push " " - Call StrRep - Pop $R0 - StrCpy $READABLE $R0 - Push $1 - Push "-" - Push "_" - Call StrRep - Pop $R0 - StrCpy $MANPAGE $R0 - CreateDirectory "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE" - SetOutPath $INSTDIR\samples\$1 - WriteINIStr $INSTDIR\samples\$1\ManualPage.url "InternetShortcut" "URL" "http://panda3d.org/wiki/index.php/Sample_Programs:_$MANPAGE" - CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\Manual Page.lnk" "$INSTDIR\samples\$1\ManualPage.url" "" "$INSTDIR\bin\eggcacher.exe" 0 "" "" "Manual Entry on this Sample Program" - CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\View Source Code.lnk" "$INSTDIR\samples\$1" - FindFirst $2 $3 $INSTDIR\samples\$1\Tut-*.py - iloop: - StrCmp $3 "" idone - StrCpy $TUTNAME $3 -3 4 - Push $TUTNAME - Push "-" - Push " " - Call StrRep - Pop $R0 - StrCpy $TUTNAME $R0 - CreateShortCut "$SMPROGRAMS\${SMDIRECTORY}\Sample Programs\$READABLE\Run $TUTNAME.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $TUTNAME" - CreateShortCut "$INSTDIR\samples\$1\Run $TUTNAME.lnk" "$INSTDIR\python\python.exe" "-E $3" "$INSTDIR\bin\eggcacher.exe" 0 SW_SHOWMINIMIZED "" "Run $TUTNAME" - FindNext $2 $3 - goto iloop - idone: - next: - FindNext $0 $1 - Goto loop - done: - - !endif - -SectionEnd - - -Section -post - - !ifdef REGVIEW - SetRegView ${REGVIEW} - !endif - - !ifndef PPGAME - - # Add the "bin" directory to the PATH. - Push "$INSTDIR\python" - Call RemoveFromPath - Push "$INSTDIR\python\Scripts" - Call RemoveFromPath - Push "$INSTDIR\bin" - Call RemoveFromPath - Push "$INSTDIR\python" - Call AddToPath - Push "$INSTDIR\python\Scripts" - Call AddToPath - Push "$INSTDIR\bin" - Call AddToPath - - ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" "" - StrCmp $0 "$INSTDIR\python" RegPath 0 - StrCmp $0 "" RegPath 0 - - MessageBox MB_YESNO|MB_ICONQUESTION \ - "Your system already has a copy of Python installed. Panda3D installs its own copy of Python ${PYVER}, which will install alongside your existing copy. Would you like to make Panda's copy the default Python? If you choose 'No', you will have to configure your existing copy of Python to use the Panda3D libraries, keeping in mind that this version of Panda3D can only run with Python ${PYVER}." \ - IDNO SkipRegPath - - RegPath: - DetailPrint "Adding registry keys for python..." - WriteRegStr HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" "" "$INSTDIR\python" - SkipRegPath: - !endif - - DetailPrint "Adding the uninstaller ..." - Delete "$INSTDIR\uninst.exe" - WriteUninstaller "$INSTDIR\uninst.exe" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" "DisplayName" "${SMDIRECTORY}" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" "UninstallString" '"$INSTDIR\uninst.exe"' - SetOutPath $INSTDIR - CreateShortcut "$SMPROGRAMS\${SMDIRECTORY}\Uninstall ${NAME}.lnk" "$INSTDIR\uninst.exe" "" - -SectionEnd - -Section Uninstall - - !ifdef REGVIEW - SetRegView ${REGVIEW} - !endif - - !ifndef PPGAME - Push "$INSTDIR\python" - Call un.RemoveFromPath - Push "$INSTDIR\python\Scripts" - Call un.RemoveFromPath - Push "$INSTDIR\bin" - Call un.RemoveFromPath - - ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" "" - StrCmp $0 "$INSTDIR\python" 0 SkipUnReg - DeleteRegKey HKLM "Software\Python\PythonCore\${PYVER}" - SkipUnReg: - !endif - - Delete "$INSTDIR\uninst.exe" - RMDir /r "$SMPROGRAMS\${SMDIRECTORY}" - RMDir /r "$INSTDIR" - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SMDIRECTORY}" - -SectionEnd - -# --[ Utility Functions ]------------------------------------------------------ - -; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 -Function IsNT - Push $0 - ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion - StrCmp $0 "" 0 IsNT_yes - ; we are not NT. - Pop $0 - Push 0 - Return - IsNT_yes: - ; NT!!! - Pop $0 - Push 1 -FunctionEnd - -; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 -Function un.IsNT - Push $0 - ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion - StrCmp $0 "" 0 unIsNT_yes - ; we are not NT. - Pop $0 - Push 0 - Return - unIsNT_yes: - ; NT!!! - Pop $0 - Push 1 -FunctionEnd - -; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 -Function StrStr - Push $0 - Exch - Pop $0 ; $0 now have the string to find - Push $1 - Exch 2 - Pop $1 ; $1 now have the string to find in - Exch - Push $2 - Push $3 - Push $4 - Push $5 - StrCpy $2 -1 - StrLen $3 $0 - StrLen $4 $1 - IntOp $4 $4 - $3 - unStrStr_loop: - IntOp $2 $2 + 1 - IntCmp $2 $4 0 0 unStrStrReturn_notFound - StrCpy $5 $1 $3 $2 - StrCmp $5 $0 unStrStr_done unStrStr_loop - unStrStrReturn_notFound: - StrCpy $2 -1 - unStrStr_done: - Pop $5 - Pop $4 - Pop $3 - Exch $2 - Exch 2 - Pop $0 - Pop $1 -FunctionEnd - -; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 -Function un.StrStr - Push $0 - Exch - Pop $0 ; $0 now have the string to find - Push $1 - Exch 2 - Pop $1 ; $1 now have the string to find in - Exch - Push $2 - Push $3 - Push $4 - Push $5 - StrCpy $2 -1 - StrLen $3 $0 - StrLen $4 $1 - IntOp $4 $4 - $3 - unStrStr_loop: - IntOp $2 $2 + 1 - IntCmp $2 $4 0 0 unStrStrReturn_notFound - StrCpy $5 $1 $3 $2 - StrCmp $5 $0 unStrStr_done unStrStr_loop - unStrStrReturn_notFound: - StrCpy $2 -1 - unStrStr_done: - Pop $5 - Pop $4 - Pop $3 - Exch $2 - Exch 2 - Pop $0 - Pop $1 -FunctionEnd - -; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 -; Commentary and smarter ';' checking by Jon Parise -Function AddToPath - Exch $0 - Push $1 - Push $2 - Push $3 - Call IsNT - Pop $1 - - StrCmp $1 1 AddToPath_NT - ; We're not on NT, so modify the AUTOEXEC.BAT file. - StrCpy $1 $WINDIR 2 - FileOpen $1 "$1\autoexec.bat" a - FileSeek $1 0 END - GetFullPathName /SHORT $0 $0 - FileWrite $1 "$\r$\nSET PATH=%PATH%;$0$\r$\n" - FileClose $1 - Goto AddToPath_done - - AddToPath_NT: - ReadRegStr $1 HKCU "Environment" "PATH" - Call IsUserAdmin - Pop $3 - ; If this is an Admin user, use the System env. variable instead of the user's env. variable - StrCmp $3 1 0 +2 - ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" - - ; If the PATH string is empty, jump over the mangling routines. - StrCmp $1 "" AddToPath_NTdoIt - - ; Pull off the last character of the PATH string. If it's a semicolon, - ; we don't need to add another one, so jump to the section where we - ; append the new PATH component(s). - StrCpy $2 $1 1 -1 - StrCmp $2 ";" AddToPath_NTAddPath AddToPath_NTAddSemi - - AddToPath_NTAddSemi: - StrCpy $1 "$1;" - Goto AddToPath_NTAddPath - AddToPath_NTAddPath: - StrCpy $0 "$1$0" - Goto AddToPath_NTdoIt - AddToPath_NTdoIt: - Call IsUserAdmin - Pop $3 - StrCmp $3 1 0 NotAdmin - WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $0 - Goto AddToPath_done - - NotAdmin: - WriteRegExpandStr HKCU "Environment" "PATH" $0 - AddToPath_done: - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - -; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 -Function RemoveFromPath - Exch $0 - Push $1 - Push $2 - Push $3 - Push $4 - Push $5 - Call IsNT - Pop $1 - StrCmp $1 1 unRemoveFromPath_NT - ; Not on NT - StrCpy $1 $WINDIR 2 - FileOpen $1 "$1\autoexec.bat" r - GetTempFileName $4 - FileOpen $2 $4 w - GetFullPathName /SHORT $0 $0 - StrCpy $0 "SET PATH=%PATH%;$0" - SetRebootFlag true - Goto unRemoveFromPath_dosLoop - - unRemoveFromPath_dosLoop: - FileRead $1 $3 - StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop - StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop - StrCmp $3 "$0" unRemoveFromPath_dosLoop - StrCmp $3 "" unRemoveFromPath_dosLoopEnd - FileWrite $2 $3 - Goto unRemoveFromPath_dosLoop - - unRemoveFromPath_dosLoopEnd: - FileClose $2 - FileClose $1 - StrCpy $1 $WINDIR 2 - Delete "$1\autoexec.bat" - CopyFiles /SILENT $4 "$1\autoexec.bat" - Delete $4 - Goto unRemoveFromPath_done - - unRemoveFromPath_NT: - StrLen $2 $0 - Call IsUserAdmin - Pop $5 - StrCmp $5 1 0 NotAdmin - ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" - Push $1 - Push $0 - Call StrStr ; Find $0 in $1 - Pop $0 ; pos of our dir - IntCmp $0 -1 unRemoveFromPath_done - ; else, it is in path - StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir - IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';') - IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon. - StrLen $0 $1 - StrCpy $1 $1 $0 $2 - StrCpy $3 "$3$1" - WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3 - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - Goto unRemoveFromPath_done - - - NotAdmin: - ReadRegStr $1 HKCU "Environment" "PATH" - Push $1 - Push $0 - Call StrStr ; Find $0 in $1 - Pop $0 ; pos of our dir - IntCmp $0 -1 unRemoveFromPath_done - ; else, it is in path - StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir - IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';') - IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon. - StrLen $0 $1 - StrCpy $1 $1 $0 $2 - StrCpy $3 "$3$1" - WriteRegExpandStr HKCU "Environment" "PATH" $3 - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - - unRemoveFromPath_done: - Pop $5 - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - -; From: http://nsis.sourceforge.net/archive/viewpage.php?pageid=91 -Function un.RemoveFromPath - Exch $0 - Push $1 - Push $2 - Push $3 - Push $4 - Push $5 - Call un.IsNT - Pop $1 - StrCmp $1 1 unRemoveFromPath_NT - ; Not on NT - StrCpy $1 $WINDIR 2 - FileOpen $1 "$1\autoexec.bat" r - GetTempFileName $4 - FileOpen $2 $4 w - GetFullPathName /SHORT $0 $0 - StrCpy $0 "SET PATH=%PATH%;$0" - SetRebootFlag true - Goto unRemoveFromPath_dosLoop - - unRemoveFromPath_dosLoop: - FileRead $1 $3 - StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoop - StrCmp $3 "$0$\n" unRemoveFromPath_dosLoop - StrCmp $3 "$0" unRemoveFromPath_dosLoop - StrCmp $3 "" unRemoveFromPath_dosLoopEnd - FileWrite $2 $3 - Goto unRemoveFromPath_dosLoop - - unRemoveFromPath_dosLoopEnd: - FileClose $2 - FileClose $1 - StrCpy $1 $WINDIR 2 - Delete "$1\autoexec.bat" - CopyFiles /SILENT $4 "$1\autoexec.bat" - Delete $4 - Goto unRemoveFromPath_done - - unRemoveFromPath_NT: - StrLen $2 $0 - Call un.IsUserAdmin - Pop $5 - StrCmp $5 1 0 NotAdmin - ReadRegStr $1 HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" - Push $1 - Push $0 - Call un.StrStr ; Find $0 in $1 - Pop $0 ; pos of our dir - IntCmp $0 -1 unRemoveFromPath_done - ; else, it is in path - StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir - IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';') - IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon. - StrLen $0 $1 - StrCpy $1 $1 $0 $2 - StrCpy $3 "$3$1" - WriteRegExpandStr HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment" "PATH" $3 - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - Goto unRemoveFromPath_done - - - NotAdmin: - ReadRegStr $1 HKCU "Environment" "PATH" - Push $1 - Push $0 - Call un.StrStr ; Find $0 in $1 - Pop $0 ; pos of our dir - IntCmp $0 -1 unRemoveFromPath_done - ; else, it is in path - StrCpy $3 $1 $0 ; $3 now has the part of the path before our dir - IntOp $2 $2 + $0 ; $2 now contains the pos after our dir in the path (';') - IntOp $2 $2 + 1 ; $2 now containts the pos after our dir and the semicolon. - StrLen $0 $1 - StrCpy $1 $1 $0 $2 - StrCpy $3 "$3$1" - WriteRegExpandStr HKCU "Environment" "PATH" $3 - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - - unRemoveFromPath_done: - Pop $5 - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - -; From: http://nsis.sourceforge.net/archive/nsisweb.php?page=329&instances=0,11 -; Localized by Ben Johnson (bkj@andrew.cmu.edu) -Function IsUserAdmin - Push $0 - Push $1 - Push $2 - Push $3 - Call IsNT - Pop $1 - - ClearErrors - UserInfo::GetName - ;IfErrors Win9x - Pop $2 - UserInfo::GetAccountType - Pop $3 - - ; Compare results of IsNT with "1" - StrCmp $1 1 0 NotNT - ;This is NT - - - StrCmp $3 "Admin" 0 NotAdmin - ; Observation: I get here when running Win98SE. (Lilla) - ; The functions UserInfo.dll looks for are there on Win98 too, - ; but just don't work. So UserInfo.dll, knowing that admin isn't required - ; on Win98, returns admin anyway. (per kichik) - ; MessageBox MB_OK 'User "$R1" is in the Administrators group' - Pop $3 - Pop $2 - Pop $1 - Pop $0 - - Push 1 - Return - - NotAdmin: - ; You should still check for an empty string because the functions - ; UserInfo.dll looks for may not be present on Windows 95. (per kichik) - - #StrCmp $2 "" Win9x - #StrCpy $0 0 - ;MessageBox MB_OK 'User "$2" is in the "$3" group' - Pop $3 - Pop $2 - Pop $1 - Pop $0 - - Push 0 - Return - - ;Because we use IsNT, this is redundant. - #Win9x: - # ; comment/message below is by UserInfo.nsi author: - # ; This one means you don't need to care about admin or - # ; not admin because Windows 9x doesn't either - # ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!" - # StrCpy $0 0 - - NotNT: - ;We are not NT - ;Win9x doesn't have "admin" users. - ;Let the user do whatever. - Pop $3 - Pop $2 - Pop $1 - Pop $0 - - Push 1 - -FunctionEnd - -Function un.IsUserAdmin - Push $0 - Push $1 - Push $2 - Push $3 - Call un.IsNT - Pop $1 - - ClearErrors - UserInfo::GetName - ;IfErrors Win9x - Pop $2 - UserInfo::GetAccountType - Pop $3 - - ; Compare results of IsNT with "1" - StrCmp $1 1 0 NotNT - ;This is NT - - - StrCmp $3 "Admin" 0 NotAdmin - ; Observation: I get here when running Win98SE. (Lilla) - ; The functions UserInfo.dll looks for are there on Win98 too, - ; but just don't work. So UserInfo.dll, knowing that admin isn't required - ; on Win98, returns admin anyway. (per kichik) - ; MessageBox MB_OK 'User "$R1" is in the Administrators group' - Pop $3 - Pop $2 - Pop $1 - Pop $0 - - Push 1 - Return - - NotAdmin: - ; You should still check for an empty string because the functions - ; UserInfo.dll looks for may not be present on Windows 95. (per kichik) - - #StrCmp $2 "" Win9x - #StrCpy $0 0 - ;MessageBox MB_OK 'User "$2" is in the "$3" group' - Pop $3 - Pop $2 - Pop $1 - Pop $0 - - Push 0 - Return - - ;Because we use IsNT, this is redundant. - #Win9x: - # ; comment/message below is by UserInfo.nsi author: - # ; This one means you don't need to care about admin or - # ; not admin because Windows 9x doesn't either - # ;MessageBox MB_OK "Error! This DLL can't run under Windows 9x!" - # StrCpy $0 0 - - NotNT: - ;We are not NT - ;Win9x doesn't have "admin" users. - ;Let the user do whatever. - Pop $3 - Pop $2 - Pop $1 - Pop $0 - - Push 1 - -FunctionEnd - -Function StrRep - - ;Written by dirtydingus 2003-02-20 04:30:09 - ; USAGE - ;Push String to do replacement in (haystack) - ;Push String to replace (needle) - ;Push Replacement - ;Call StrRep - ;Pop $R0 result - ;StrCpy $Result STR $R0 - - Exch $R4 ; $R4 = Replacement String - Exch - Exch $R3 ; $R3 = String to replace (needle) - Exch 2 - Exch $R1 ; $R1 = String to do replacement in (haystack) - Push $R2 ; Replaced haystack - Push $R5 ; Len (needle) - Push $R6 ; len (haystack) - Push $R7 ; Scratch reg - StrCpy $R2 "" - StrLen $R5 $R3 - StrLen $R6 $R1 -loop: - StrCpy $R7 $R1 $R5 - StrCmp $R7 $R3 found - StrCpy $R7 $R1 1 ; - optimization can be removed if U know len needle=1 - StrCpy $R2 "$R2$R7" - StrCpy $R1 $R1 $R6 1 - StrCmp $R1 "" done loop -found: - StrCpy $R2 "$R2$R4" - StrCpy $R1 $R1 $R6 $R5 - StrCmp $R1 "" done loop -done: - StrCpy $R3 $R2 - Pop $R7 - Pop $R6 - Pop $R5 - Pop $R2 - Pop $R1 - Pop $R4 - Exch $R3 - -FunctionEnd - diff --git a/direct/src/directscripts/packpanda.py b/direct/src/directscripts/packpanda.py deleted file mode 100755 index c195017f04..0000000000 --- a/direct/src/directscripts/packpanda.py +++ /dev/null @@ -1,424 +0,0 @@ -############################################################################# -# -# packpanda - this is a tool that packages up a panda game into a -# convenient, easily-downloaded windows executable. Packpanda runs on linux -# and windows - on linux, it builds .debs and .rpms, on windows it relies on -# NSIS, the nullsoft scriptable install system, to do the hard work. -# -# This is intentionally a very simplistic game-packer with very -# limited options. The goal is simplicity, not feature richness. -# There are dozens of complex, powerful packaging tools already out -# there. This one is for people who just want to do it quick and -# easy. -# -############################################################################## - -import sys, os, getopt, shutil, py_compile, subprocess - -OPTIONLIST = [ -("dir", 1, "Name of directory containing game"), -("name", 1, "Human-readable name of the game"), -("version", 1, "Version number to add to game name"), -("rmdir", 2, "Delete all directories with given name"), -("rmext", 2, "Delete all files with given extension"), -("fast", 0, "Use fast compression instead of good compression"), -("bam", 0, "Generate BAM files, change default-model-extension to BAM"), -("pyc", 0, "Generate PYC files"), -] - -def ParseFailure(): - print("") - print("packpanda usage:") - print("") - for (opt, hasval, explanation) in OPTIONLIST: - if (hasval): - print(" --%-10s %s"%(opt+" x", explanation)) - else: - print(" --%-10s %s"%(opt+" ", explanation)) - sys.exit(1) - -def ParseOptions(args): - try: - options = {} - longopts = [] - for (opt, hasval, explanation) in OPTIONLIST: - if (hasval==2): - longopts.append(opt+"=") - options[opt] = [] - elif (hasval==1): - longopts.append(opt+"=") - options[opt] = "" - else: - longopts.append(opt) - options[opt] = 0 - opts, extras = getopt.getopt(args, "", longopts) - for option, value in opts: - for (opt, hasval, explanation) in OPTIONLIST: - if (option == "--"+opt): - if (hasval==2): options[opt].append(value) - elif (hasval==1): options[opt] = value - else: options[opt] = 1 - return options - except: ParseFailure(); - -OPTIONS = ParseOptions(sys.argv[1:]) - -############################################################################## -# -# Locate the relevant trees. -# -############################################################################## - -PANDA=None -for dir in sys.path: - if (dir != "") and os.path.exists(os.path.join(dir,"direct")) and os.path.exists(os.path.join(dir,"pandac")): - PANDA=os.path.abspath(dir) -if (PANDA is None): - sys.exit("Cannot locate the panda root directory in the python path (cannot locate directory containing direct and pandac).") -print("PANDA located at "+PANDA) - -if (os.path.exists(os.path.join(PANDA,"..","makepanda","makepanda.py"))) and (sys.platform != "win32" or os.path.exists(os.path.join(PANDA,"..","thirdparty","win-nsis","makensis.exe"))): - PSOURCE=os.path.abspath(os.path.join(PANDA,"..")) - if (sys.platform == "win32"): - NSIS=os.path.abspath(os.path.join(PANDA,"..","thirdparty","win-nsis")) -else: - PSOURCE=PANDA - if (sys.platform == "win32"): - NSIS=os.path.join(PANDA,"nsis") - -############################################################################## -# -# Identify the main parts of the game: DIR, NAME, MAIN, ICON, BITMAP, etc -# -############################################################################## - -VER=OPTIONS["version"] -DIR=OPTIONS["dir"] -if (DIR==""): - print("You must specify the --dir option.") - ParseFailure() -DIR=os.path.abspath(DIR) -MYDIR=os.path.abspath(os.getcwd()) -BASENAME=os.path.basename(DIR) -if (OPTIONS["name"] != ""): - NAME=OPTIONS["name"] -else: - NAME=BASENAME -SMDIRECTORY=NAME -if (VER!=""): SMDIRECTORY=SMDIRECTORY+" "+VER -PYTHONV="python"+sys.version[:3] -LICENSE=os.path.join(DIR, "license.txt") -OUTFILE=os.path.basename(DIR) -if (VER!=""): OUTFILE=OUTFILE+"-"+VER -if (sys.platform == "win32"): - ICON=os.path.join(DIR, "icon.ico") - BITMAP=os.path.join(DIR, "installer.bmp") - OUTFILE=os.path.abspath(OUTFILE+".exe") - INSTALLDIR='C:\\'+os.path.basename(DIR) - if (VER!=""): INSTALLDIR=INSTALLDIR+"-"+VER - COMPRESS="lzma" - if (OPTIONS["fast"]): COMPRESS="zlib" -if (OPTIONS["pyc"]): MAIN="main.pyc" -else: MAIN="main.py" - -def PrintFileStatus(label, file): - if (os.path.exists(file)): - print("%-15s: %s"%(label, file)) - else: - print("%-15s: %s (MISSING)"%(label, file)) - -PrintFileStatus("Dir", DIR) -print("%-15s: %s"%("Name", NAME)) -print("%-15s: %s"%("Start Menu", SMDIRECTORY)) -PrintFileStatus("Main", os.path.join(DIR, MAIN)) -if (sys.platform == "win32"): - PrintFileStatus("Icon", ICON) - PrintFileStatus("Bitmap", BITMAP) -PrintFileStatus("License", LICENSE) -print("%-15s: %s"%("Output", OUTFILE)) -if (sys.platform == "win32"): - print("%-15s: %s"%("Install Dir", INSTALLDIR)) - -if (os.path.isdir(DIR)==0): - sys.exit("Difficulty reading "+DIR+". Cannot continue.") - -if (os.path.isfile(os.path.join(DIR, "main.py"))==0): - sys.exit("Difficulty reading main.py. Cannot continue.") - -if (os.path.isfile(LICENSE)==0): - LICENSE=os.path.join(PANDA,"LICENSE") - -if (sys.platform == "win32") and (os.path.isfile(BITMAP)==0): - BITMAP=os.path.join(NSIS,"Contrib","Graphics","Wizard","nsis.bmp") - -if (sys.platform == "win32"): - if (os.path.isfile(ICON)==0): - PPICON="bin\\ppython.exe" - else: - PPICON="game\\icon.ico" - -############################################################################## -# -# Copy the game to a temporary directory, so we can modify it safely. -# -############################################################################## - -def limitedCopyTree(src, dst, rmdir): - if (os.path.isdir(src)): - if (os.path.basename(src) in rmdir): - return - if (not os.path.isdir(dst)): os.mkdir(dst) - for x in os.listdir(src): - limitedCopyTree(os.path.join(src,x), os.path.join(dst,x), rmdir) - else: - shutil.copyfile(src, dst) - - -TMPDIR=os.path.abspath("packpanda-TMP") -if (sys.platform == "win32"): - TMPGAME=os.path.join(TMPDIR,"game") - TMPETC=os.path.join(TMPDIR,"etc") -else: - TMPGAME=os.path.join(TMPDIR,"usr","share","games",BASENAME,"game") - TMPETC=os.path.join(TMPDIR,"usr","share","games",BASENAME,"etc") -print("") -print("Copying the game to "+TMPDIR+"...") -if (os.path.exists(TMPDIR)): - try: shutil.rmtree(TMPDIR) - except: sys.exit("Cannot delete "+TMPDIR) -try: - os.mkdir(TMPDIR) - rmdir = {} - for x in OPTIONS["rmdir"]: - rmdir[x] = 1 - if not os.path.isdir( TMPGAME ): - os.makedirs(TMPGAME) - limitedCopyTree(DIR, TMPGAME, rmdir) - if not os.path.isdir( TMPETC ): - os.makedirs(TMPETC) - if sys.platform == "win32": - limitedCopyTree(os.path.join(PANDA, "etc"), TMPETC, {}) - else: - shutil.copyfile("/etc/Config.prc", os.path.join(TMPETC, "Config.prc")) - shutil.copyfile("/etc/Confauto.prc", os.path.join(TMPETC, "Confauto.prc")) -except: sys.exit("Cannot copy game to "+TMPDIR) - -############################################################################## -# -# If --bam requested, change default-model-extension .egg to bam. -# -############################################################################## - -def ReadFile(wfile): - try: - srchandle = open(wfile, "rb") - data = srchandle.read() - srchandle.close() - return data - except: exit("Cannot read "+wfile) - -def WriteFile(wfile,data): - try: - dsthandle = open(wfile, "wb") - dsthandle.write(data) - dsthandle.close() - except: exit("Cannot write "+wfile) - -if OPTIONS["bam"]: - CONF=ReadFile(os.path.join(TMPETC,"Confauto.prc")) - CONF=CONF.replace("default-model-extension .egg","default-model-extension .bam") - WriteFile(os.path.join(TMPETC,"Confauto.prc"), CONF) - -############################################################################## -# -# Compile all py files, convert all egg files. -# -# We do this as a sanity check, even if the user -# hasn't requested that his files be compiled. -# -############################################################################## - -if (sys.platform == "win32"): - EGG2BAM=os.path.join(PANDA,"bin","egg2bam.exe") -else: - EGG2BAM=os.path.join(PANDA,"bin","egg2bam") - -def egg2bam(file,bam): - present = os.path.exists(bam) - if (present): bam = "packpanda-TMP.bam"; - cmd = 'egg2bam -noabs -ps rel -pd . "'+file+'" -o "'+bam+'"' - print("Executing: "+cmd) - if (sys.platform == "win32"): - res = os.spawnl(os.P_WAIT, EGG2BAM, cmd) - else: - res = os.system(cmd) - if (res != 0): sys.exit("Problem in egg file: "+file) - if (present) or (OPTIONS["bam"]==0): - os.unlink(bam) - -def py2pyc(file): - print("Compiling python "+file) - pyc = file[:-3]+'.pyc' - pyo = file[:-3]+'.pyo' - if (os.path.exists(pyc)): os.unlink(pyc) - if (os.path.exists(pyo)): os.unlink(pyo) - try: py_compile.compile(file) - except: sys.exit("Cannot compile "+file) - if (OPTIONS["pyc"]==0): - if (os.path.exists(pyc)): - os.unlink(pyc) - if (os.path.exists(pyo)): - os.unlink(pyo) - -def CompileFiles(file): - if (os.path.isfile(file)): - if (file.endswith(".egg")): - egg2bam(file, file[:-4]+'.bam') - elif (file.endswith(".egg.pz") or file.endswith(".egg.gz")): - egg2bam(file, file[:-7]+'.bam') - elif (file.endswith(".py")): - py2pyc(file) - else: pass - elif (os.path.isdir(file)): - for x in os.listdir(file): - CompileFiles(os.path.join(file, x)) - -def DeleteFiles(file): - base = os.path.basename(file).lower() - if (os.path.isdir(file)): - for pattern in OPTIONS["rmdir"]: - if pattern.lower() == base: - print("Deleting "+file) - shutil.rmtree(file) - return - for x in os.listdir(file): - DeleteFiles(os.path.join(file, x)) - else: - for ext in OPTIONS["rmext"]: - if base[-(len(ext) + 1):] == ("." + ext).lower(): - print("Deleting "+file) - os.unlink(file) - return - -print("") -print("Compiling BAM and PYC files...") -os.chdir(TMPGAME) -CompileFiles(".") -DeleteFiles(".") - -############################################################################## -# -# Now make the installer. Yay! -# -############################################################################## - -INSTALLER_DEB_FILE=""" -Package: BASENAME -Version: VERSION -Section: games -Priority: optional -Architecture: ARCH -Essential: no -Depends: PYTHONV -Provides: BASENAME -Description: NAME -Maintainer: Unknown -""" - -INSTALLER_SPEC_FILE=""" -Summary: NAME -Name: BASENAME -Version: VERSION -Release: 1 -Group: Amusement/Games -License: See license file -BuildRoot: TMPDIR -BuildRequires: PYTHONV -%description -NAME -%files -%defattr(-,root,root) -/usr/bin/BASENAME -/usr/lib/games/BASENAME -/usr/share/games/BASENAME -""" - -RUN_SCRIPT=""" -#!/bin/sh -cd /usr/share/games/BASENAME/game -PYTHONPATH=/usr/lib/games/BASENAME:/usr/share/games/BASENAME -LD_LIBRARY_PATH=/usr/lib/games/BASENAME -PYTHONV MAIN -""" - -if (sys.platform == "win32"): - CMD="\""+NSIS+"\\makensis.exe\" /V2 " - CMD=CMD+'/DCOMPRESSOR="'+COMPRESS+'" ' - CMD=CMD+'/DNAME="'+NAME+'" ' - CMD=CMD+'/DSMDIRECTORY="'+SMDIRECTORY+'" ' - CMD=CMD+'/DINSTALLDIR="'+INSTALLDIR+'" ' - CMD=CMD+'/DOUTFILE="'+OUTFILE+'" ' - CMD=CMD+'/DLICENSE="'+LICENSE+'" ' - CMD=CMD+'/DLANGUAGE="English" ' - CMD=CMD+'/DRUNTEXT="Play '+NAME+'" ' - CMD=CMD+'/DIBITMAP="'+BITMAP+'" ' - CMD=CMD+'/DUBITMAP="'+BITMAP+'" ' - CMD=CMD+'/DPANDA="'+PANDA+'" ' - CMD=CMD+'/DPANDACONF="'+TMPETC+'" ' - CMD=CMD+'/DPSOURCE="'+PSOURCE+'" ' - CMD=CMD+'/DPPGAME="'+TMPGAME+'" ' - CMD=CMD+'/DPPMAIN="'+MAIN+'" ' - CMD=CMD+'/DPPICON="'+PPICON+'" ' - CMD=CMD+'"'+PSOURCE+'\\direct\\directscripts\\packpanda.nsi"' - - print("") - print(CMD) - print("packing...") - subprocess.call(CMD) -else: - os.chdir(MYDIR) - os.system("mkdir -p %s/usr/bin" % TMPDIR) - os.system("mkdir -p %s/usr/share/games/%s" % (TMPDIR, BASENAME)) - os.system("mkdir -p %s/usr/lib/games/%s" % (TMPDIR, BASENAME)) - os.system("cp --recursive %s/direct %s/usr/share/games/%s/direct" % (PANDA, TMPDIR, BASENAME)) - os.system("cp --recursive %s/pandac %s/usr/share/games/%s/pandac" % (PANDA, TMPDIR, BASENAME)) - os.system("cp --recursive %s/models %s/usr/share/games/%s/models" % (PANDA, TMPDIR, BASENAME)) - os.system("cp --recursive %s/Pmw %s/usr/share/games/%s/Pmw" % (PANDA, TMPDIR, BASENAME)) - os.system("cp %s %s/usr/share/games/%s/LICENSE" % (LICENSE, TMPDIR, BASENAME)) - os.system("cp --recursive /usr/lib/panda3d/* %s/usr/lib/games/%s/" % (TMPDIR, BASENAME)) - - # Make the script to run the game - txt = RUN_SCRIPT[1:].replace("BASENAME",BASENAME).replace("PYTHONV",PYTHONV).replace("MAIN",MAIN) - WriteFile(TMPDIR+"/usr/bin/"+BASENAME, txt) - os.system("chmod +x "+TMPDIR+"/usr/bin/"+BASENAME) - - if (os.path.exists("/usr/bin/rpmbuild")): - os.system("rm -rf %s/DEBIAN" % TMPDIR) - os.system("rpm -E '%_target_cpu' > packpanda-TMP.txt") - ARCH=ReadFile("packpanda-TMP.txt").strip() - os.remove("packpanda-TMP.txt") - txt = INSTALLER_SPEC_FILE[1:].replace("VERSION",VER).replace("TMPDIR",TMPDIR) - txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("PYTHONV",PYTHONV) - WriteFile("packpanda-TMP.spec", txt) - os.system("rpmbuild --define '_rpmdir "+TMPDIR+"' -bb packpanda-TMP.spec") - os.system("mv "+ARCH+"/"+BASENAME+"-"+VER+"-1."+ARCH+".rpm .") - os.rmdir(ARCH) - os.remove("packpanda-TMP.spec") - - if (os.path.exists("/usr/bin/dpkg-deb")): - os.system("dpkg --print-architecture > packpanda-TMP.txt") - ARCH=ReadFile("packpanda-TMP.txt").strip() - os.remove("packpanda-TMP.txt") - txt = INSTALLER_DEB_FILE[1:].replace("VERSION",str(VER)).replace("PYTHONV",PYTHONV) - txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("ARCH",ARCH) - os.system("mkdir -p %s/DEBIAN" % TMPDIR) - os.system("cd %s ; (find usr -type f -exec md5sum {} \;) > DEBIAN/md5sums" % TMPDIR) - WriteFile(TMPDIR+"/DEBIAN/control",txt) - os.system("dpkg-deb -b "+TMPDIR+" "+BASENAME+"_"+VER+"_"+ARCH+".deb") - - if not(os.path.exists("/usr/bin/rpmbuild") or os.path.exists("/usr/bin/dpkg-deb")): - exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!") - -# Dummy main function so this can be added to console_scripts. -def main(): - return 0 diff --git a/makepanda/installer.nsi b/makepanda/installer.nsi index d004d15006..c5e76fc766 100755 --- a/makepanda/installer.nsi +++ b/makepanda/installer.nsi @@ -619,13 +619,10 @@ Section -post DetailPrint "Preloading .egg files into the model cache..." SetDetailsPrint listonly - ; We need to set the $PATH for eggcacher. SetOutPath $INSTDIR - ReadEnvStr $R0 "PATH" - StrCpy $R0 "$INSTDIR\python;$INSTDIR\bin;$R0" - System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("PATH", R0).r2' - - nsExec::ExecToLog '"$INSTDIR\bin\eggcacher.exe" --concise models samples' + nsExec::ExecToLog '"$INSTDIR\python\python.exe" -m direct.directscripts.eggcacher --concise models samples' + Pop $0 + DetailPrint "Command returned exit status $0" SetDetailsPrint both DetailPrint "Writing the uninstaller ..." diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 2e54cc2058..4faa683f87 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -90,7 +90,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support "ROCKET", "AWESOMIUM", # GUI libraries "CARBON", "COCOA", # Mac OS X toolkits "X11", # Unix platform support - "PANDATOOL", "PVIEW", "DEPLOYTOOLS", "DIRECTSCRIPTS",# Toolchain + "PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain "SKEL", # Example SKEL project "PANDAFX", # Some distortion special lenses "PANDAPARTICLESYSTEM", # Built in particle system @@ -172,7 +172,7 @@ def parseopts(args): "version=","lzma","no-python","threads=","outputdir=","override=", "static","host=","debversion=","rpmrelease=","p3dsuffix=","rtdist-version=", "directx-sdk=", "windows-sdk=", "msvc-version=", "clean", "use-icl", - "universal", "target=", "arch=", "git-commit=", + "universal", "target=", "arch=", "git-commit=", "no-directscripts", "use-touchinput", "no-touchinput"] anything = 0 optimize = "" @@ -224,6 +224,7 @@ def parseopts(args): # Backward compatibility, OPENGL was renamed to GL elif (option=="--use-opengl"): PkgEnable("GL") elif (option=="--no-opengl"): PkgDisable("GL") + elif (option=="--no-directscripts"): pass elif (option=="--directx-sdk"): STRDXSDKVERSION = value.strip().lower() if STRDXSDKVERSION == '': @@ -832,7 +833,11 @@ if (COMPILER=="GCC"): SmartPkgEnable("ROCKET", "", rocket_libs, "Rocket/Core.h") if not PkgSkip("PYTHON"): - SmartPkgEnable("PYTHON", "", SDK["PYTHONVERSION"], (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config") + python_lib = SDK["PYTHONVERSION"] + if not RTDIST: + # We don't link anything in the SDK with libpython. + python_lib = "" + SmartPkgEnable("PYTHON", "", python_lib, (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h"), tool = SDK["PYTHONVERSION"] + "-config") SmartPkgEnable("OPENSSL", "openssl", ("ssl", "crypto"), ("openssl/ssl.h", "openssl/crypto.h")) SmartPkgEnable("ZLIB", "zlib", ("z"), "zlib.h") @@ -4996,17 +5001,6 @@ if (PkgSkip("DIRECT")==0): OPTS=['DIR:direct/src/directbase', 'PYTHON'] TargetAdd('p3directbase_directbase.obj', opts=OPTS+['BUILDING:DIRECT'], input='directbase.cxx') - if not PkgSkip("PYTHON") and not RTDIST and not RUNTIME and not PkgSkip("DIRECTSCRIPTS"): - DefSymbol("BUILDING:PACKPANDA", "IMPORT_MODULE", "direct.directscripts.packpanda") - TargetAdd('packpanda.obj', opts=OPTS+['BUILDING:PACKPANDA'], input='ppython.cxx') - TargetAdd('packpanda.exe', input='packpanda.obj') - TargetAdd('packpanda.exe', opts=['PYTHON']) - - DefSymbol("BUILDING:EGGCACHER", "IMPORT_MODULE", "direct.directscripts.eggcacher") - TargetAdd('eggcacher.obj', opts=OPTS+['BUILDING:EGGCACHER'], input='ppython.cxx') - TargetAdd('eggcacher.exe', input='eggcacher.obj') - TargetAdd('eggcacher.exe', opts=['PYTHON']) - # # DIRECTORY: direct/src/dcparser/ # diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 2eb4342b06..ee903a3940 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -1574,7 +1574,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, location = os.path.join(GetOutputDir(), "lib", os.path.basename(location)) LibName(target_pkg, location) else: - print(GetColor("cyan") + "Couldn't find library lib" + libname + " in thirdparty directory " + pkg.lower() + GetColor()) + print(GetColor("cyan") + "Couldn't find library lib" + libname + " in thirdparty directory " + thirdparty_dir + GetColor()) for d, v in defs.values(): DefSymbol(target_pkg, d, v) diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index 6d3b6fdf72..56fb43133e 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -551,7 +551,6 @@ def makewheel(version, output_dir, platform=default_platform): # Add a panda3d-tools directory containing the executables. entry_points = '[console_scripts]\n' entry_points += 'eggcacher = direct.directscripts.eggcacher:main\n' - entry_points += 'packpanda = direct.directscripts.packpanda:main\n' tools_init = '' for file in os.listdir(bin_dir): basename = os.path.splitext(file)[0] From 816b2ac3ba3f35b209dfde8afe6eee40cba358b7 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 5 Jan 2017 23:24:52 +0100 Subject: [PATCH 63/70] C++11 polyfills. This should fix Snow Leopard build. --- dtool/src/dtoolbase/dtoolbase_cc.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index eb99381c01..eb7afc9048 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -75,6 +75,7 @@ typedef int ios_seekdir; #endif #include +#include #ifdef HAVE_NAMESPACE using namespace std; @@ -114,6 +115,18 @@ typedef ios::iostate ios_iostate; typedef ios::seekdir ios_seekdir; #endif +// Apple has an outdated libstdc++. Not all is lost, though, as we can fill +// in some important missing functions. +#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20070719 +template struct remove_reference {typedef T type;}; +template struct remove_reference {typedef T type;}; +template struct remove_reference{typedef T type;}; + +template typename remove_reference::type &&move(T &&t) { + return static_cast::type&&>(t); +} +#endif + #ifdef _MSC_VER #define ALWAYS_INLINE __forceinline #elif defined(__GNUC__) @@ -153,7 +166,7 @@ typedef ios::seekdir ios_seekdir; #elif defined(__GNUC__) && (__cplusplus >= 201103L) // GCC // GCC defines several macros which we can query. List of all supported -// builtin macros: https:gcc.gnu.orgprojectscxx0x.html +// builtin macros: https://gcc.gnu.org/projects/cxx-status.html # if __cpp_constexpr >= 200704 # define CONSTEXPR constexpr # endif From 41d26284d75e47749c4488a948e038aea06c16e6 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 8 Jan 2017 13:40:09 -0500 Subject: [PATCH 64/70] Fix various compilation issues on Mac. Work around bugs in Apple Clang that ships with XCode 4 with C++11 by disabling constexpr Use move() instead of std::move() It also looks like we'll have to continue using pystub for tools that use libp3interrogatedb for now. --- dtool/src/dtoolbase/dtoolbase_cc.h | 6 +++- dtool/src/interrogate/interrogate.cxx | 3 ++ dtool/src/interrogate/interrogate_module.cxx | 3 ++ dtool/src/interrogate/parse_file.cxx | 3 ++ .../src/test_interrogate/test_interrogate.cxx | 3 ++ panda/src/display/displayRegion.I | 4 +-- panda/src/linmath/lvecBase2_src.I | 16 ---------- panda/src/linmath/lvecBase2_src.h | 4 +-- panda/src/linmath/lvecBase3_src.I | 16 ---------- panda/src/linmath/lvecBase3_src.h | 4 +-- panda/src/linmath/lvecBase4_src.I | 32 ------------------- panda/src/linmath/lvecBase4_src.h | 8 ++--- panda/src/putil/weakKeyHashMap.I | 2 +- 13 files changed, 28 insertions(+), 76 deletions(-) diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index eb7afc9048..486eaa00ba 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -118,6 +118,8 @@ typedef ios::seekdir ios_seekdir; // Apple has an outdated libstdc++. Not all is lost, though, as we can fill // in some important missing functions. #if defined(__GLIBCXX__) && __GLIBCXX__ <= 20070719 +typedef decltype(nullptr) nullptr_t; + template struct remove_reference {typedef T type;}; template struct remove_reference {typedef T type;}; template struct remove_reference{typedef T type;}; @@ -147,7 +149,9 @@ template typename remove_reference::type &&move(T &&t) { // Determine the availability of C++11 features. #if defined(__has_extension) // Clang magic. # if __has_extension(cxx_constexpr) -# define CONSTEXPR constexpr +# if !defined(__apple_build_version__) || __apple_build_version__ >= 5000000 +# define CONSTEXPR constexpr +# endif # endif # if __has_extension(cxx_noexcept) # define NOEXCEPT noexcept diff --git a/dtool/src/interrogate/interrogate.cxx b/dtool/src/interrogate/interrogate.cxx index 206132bb31..94175b9d2b 100644 --- a/dtool/src/interrogate/interrogate.cxx +++ b/dtool/src/interrogate/interrogate.cxx @@ -19,6 +19,7 @@ #include "pnotify.h" #include "panda_getopt_long.h" #include "preprocess_argv.h" +#include "pystub.h" #include CPPParser parser; @@ -305,6 +306,8 @@ predefine_macro(CPPParser& parser, const string& inoption) { int main(int argc, char **argv) { + pystub(); + preprocess_argv(argc, argv); string command_line; int i; diff --git a/dtool/src/interrogate/interrogate_module.cxx b/dtool/src/interrogate/interrogate_module.cxx index 8e397d8b9e..5feae341b7 100644 --- a/dtool/src/interrogate/interrogate_module.cxx +++ b/dtool/src/interrogate/interrogate_module.cxx @@ -19,6 +19,7 @@ #include "interrogate_interface.h" #include "interrogate_request.h" #include "load_dso.h" +#include "pystub.h" #include "pnotify.h" #include "panda_getopt_long.h" #include "preprocess_argv.h" @@ -379,6 +380,8 @@ int main(int argc, char *argv[]) { extern int optind; int flag; + pystub(); + preprocess_argv(argc, argv); flag = getopt_long_only(argc, argv, short_options, long_options, NULL); while (flag != EOF) { diff --git a/dtool/src/interrogate/parse_file.cxx b/dtool/src/interrogate/parse_file.cxx index 2b32f39561..6670bcbe44 100644 --- a/dtool/src/interrogate/parse_file.cxx +++ b/dtool/src/interrogate/parse_file.cxx @@ -22,6 +22,7 @@ #include "cppGlobals.h" #include "panda_getopt_long.h" #include "preprocess_argv.h" +#include "pystub.h" #include CPPParser parser; @@ -193,6 +194,8 @@ show_nested_types(const string &str) { int main(int argc, char **argv) { + pystub(); + extern char *optarg; extern int optind; const char *optstr = "I:S:D:o:l:vp"; diff --git a/dtool/src/test_interrogate/test_interrogate.cxx b/dtool/src/test_interrogate/test_interrogate.cxx index f9aa7c1ab4..6c2b961ff3 100644 --- a/dtool/src/test_interrogate/test_interrogate.cxx +++ b/dtool/src/test_interrogate/test_interrogate.cxx @@ -17,6 +17,7 @@ #include "interrogate_request.h" #include "load_dso.h" #include "filename.h" +#include "pystub.h" #include "panda_getopt.h" #include "preprocess_argv.h" @@ -520,6 +521,8 @@ main(int argc, char **argv) { extern int optind; const char *optstr = "p:ftqh"; + pystub(); + bool all_functions = false; bool all_types = false; bool quick_load = false; diff --git a/panda/src/display/displayRegion.I b/panda/src/display/displayRegion.I index 11492a3a5e..6004791d31 100644 --- a/panda/src/display/displayRegion.I +++ b/panda/src/display/displayRegion.I @@ -480,8 +480,8 @@ set_cull_result(PT(CullResult) cull_result, PT(SceneSetup) scene_setup, Thread *current_thread) { CDCullWriter cdata(_cycler_cull, true, current_thread); #ifdef USE_MOVE_SEMANTICS - cdata->_cull_result = std::move(cull_result); - cdata->_scene_setup = std::move(scene_setup); + cdata->_cull_result = move(cull_result); + cdata->_scene_setup = move(scene_setup); #else swap(cdata->_cull_result, cull_result); swap(cdata->_scene_setup, scene_setup); diff --git a/panda/src/linmath/lvecBase2_src.I b/panda/src/linmath/lvecBase2_src.I index 9ddce8966c..401e2e346a 100644 --- a/panda/src/linmath/lvecBase2_src.I +++ b/panda/src/linmath/lvecBase2_src.I @@ -72,14 +72,6 @@ operator [](int i) { return _v(i); } -/** - * Returns 2: the number of components of a LVecBase2. - */ -CONSTEXPR int FLOATNAME(LVecBase2):: -size() { - return 2; -} - /** * Returns true if any component of the vector is not-a-number, false * otherwise. @@ -178,14 +170,6 @@ get_data() const { return &_v(0); } -/** - * Returns the number of elements in the vector, two. - */ -CONSTEXPR int FLOATNAME(LVecBase2):: -get_num_components() { - return 2; -} - /** * Returns an iterator that may be used to traverse the elements of the * matrix, STL-style. diff --git a/panda/src/linmath/lvecBase2_src.h b/panda/src/linmath/lvecBase2_src.h index 0167855c65..d0c0693f55 100644 --- a/panda/src/linmath/lvecBase2_src.h +++ b/panda/src/linmath/lvecBase2_src.h @@ -50,7 +50,7 @@ PUBLISHED: INLINE_LINMATH FLOATTYPE operator [](int i) const; INLINE_LINMATH FLOATTYPE &operator [](int i); - CONSTEXPR static int size(); + CONSTEXPR static int size() { return 2; } INLINE_LINMATH bool is_nan() const; @@ -74,7 +74,7 @@ PUBLISHED: INLINE_LINMATH void add_y(FLOATTYPE value); INLINE_LINMATH const FLOATTYPE *get_data() const; - CONSTEXPR static int get_num_components(); + CONSTEXPR static int get_num_components() { return 2; } public: INLINE_LINMATH iterator begin(); diff --git a/panda/src/linmath/lvecBase3_src.I b/panda/src/linmath/lvecBase3_src.I index b7011da0ca..eeaea584d5 100644 --- a/panda/src/linmath/lvecBase3_src.I +++ b/panda/src/linmath/lvecBase3_src.I @@ -89,14 +89,6 @@ operator [](int i) { return _v(i); } -/** - * Returns 3: the number of components of a LVecBase3. - */ -CONSTEXPR int FLOATNAME(LVecBase3):: -size() { - return 3; -} - /** * Returns true if any component of the vector is not-a-number, false * otherwise. @@ -246,14 +238,6 @@ get_data() const { return &_v(0); } -/** - * Returns the number of elements in the vector, three. - */ -CONSTEXPR int FLOATNAME(LVecBase3):: -get_num_components() { - return 3; -} - /** * Returns an iterator that may be used to traverse the elements of the * matrix, STL-style. diff --git a/panda/src/linmath/lvecBase3_src.h b/panda/src/linmath/lvecBase3_src.h index fdc39c7819..fb9b67ca27 100644 --- a/panda/src/linmath/lvecBase3_src.h +++ b/panda/src/linmath/lvecBase3_src.h @@ -52,7 +52,7 @@ PUBLISHED: INLINE_LINMATH FLOATTYPE operator [](int i) const; INLINE_LINMATH FLOATTYPE &operator [](int i); - CONSTEXPR static int size(); + CONSTEXPR static int size() { return 3; } INLINE_LINMATH bool is_nan() const; @@ -87,7 +87,7 @@ PUBLISHED: INLINE_LINMATH void add_z(FLOATTYPE value); INLINE_LINMATH const FLOATTYPE *get_data() const; - CONSTEXPR static int get_num_components(); + CONSTEXPR static int get_num_components() { return 3; } public: INLINE_LINMATH iterator begin(); diff --git a/panda/src/linmath/lvecBase4_src.I b/panda/src/linmath/lvecBase4_src.I index 7890a6f8f0..70a376a3bf 100644 --- a/panda/src/linmath/lvecBase4_src.I +++ b/panda/src/linmath/lvecBase4_src.I @@ -118,14 +118,6 @@ operator [](int i) { return _v(i); } -/** - * Returns 4: the number of components of a LVecBase4. - */ -CONSTEXPR int FLOATNAME(LVecBase4):: -size() { - return 4; -} - /** * Returns true if any component of the vector is not-a-number, false * otherwise. @@ -288,14 +280,6 @@ get_data() const { return &_v(0); } -/** - * Returns the number of elements in the vector, four. - */ -CONSTEXPR int FLOATNAME(LVecBase4):: -get_num_components() { - return 4; -} - /** * Returns an iterator that may be used to traverse the elements of the * matrix, STL-style. @@ -958,14 +942,6 @@ operator [](int i) { return _v(i); } -/** - * Returns 4: the number of components of a LVecBase4. - */ -CONSTEXPR int FLOATNAME(UnalignedLVecBase4):: -size() { - return 4; -} - /** * Returns the address of the first of the three data elements in the vector. * The remaining elements occupy the next positions consecutively in memory. @@ -974,11 +950,3 @@ INLINE_LINMATH const FLOATTYPE *FLOATNAME(UnalignedLVecBase4):: get_data() const { return &_v(0); } - -/** - * Returns the number of elements in the vector, 4. - */ -CONSTEXPR int FLOATNAME(UnalignedLVecBase4):: -get_num_components() { - return 4; -} diff --git a/panda/src/linmath/lvecBase4_src.h b/panda/src/linmath/lvecBase4_src.h index 1d4a16e961..b6e1a4df35 100644 --- a/panda/src/linmath/lvecBase4_src.h +++ b/panda/src/linmath/lvecBase4_src.h @@ -62,7 +62,7 @@ PUBLISHED: INLINE_LINMATH FLOATTYPE operator [](int i) const; INLINE_LINMATH FLOATTYPE &operator [](int i); - CONSTEXPR static int size(); + CONSTEXPR static int size() { return 4; } INLINE_LINMATH bool is_nan() const; @@ -100,7 +100,7 @@ PUBLISHED: INLINE_LINMATH void add_w(FLOATTYPE value); INLINE_LINMATH const FLOATTYPE *get_data() const; - CONSTEXPR static int get_num_components(); + CONSTEXPR static int get_num_components() { return 4; } INLINE_LINMATH void extract_data(float*){}; public: @@ -236,10 +236,10 @@ PUBLISHED: INLINE_LINMATH FLOATTYPE operator [](int i) const; INLINE_LINMATH FLOATTYPE &operator [](int i); - CONSTEXPR static int size(); + CONSTEXPR static int size() { return 4; } INLINE_LINMATH const FLOATTYPE *get_data() const; - CONSTEXPR static int get_num_components(); + CONSTEXPR static int get_num_components() { return 4; } public: typedef FLOATTYPE numeric_type; diff --git a/panda/src/putil/weakKeyHashMap.I b/panda/src/putil/weakKeyHashMap.I index c80e47723d..b4b007f998 100644 --- a/panda/src/putil/weakKeyHashMap.I +++ b/panda/src/putil/weakKeyHashMap.I @@ -307,7 +307,7 @@ template INLINE void WeakKeyHashMap:: set_data(int n, Value &&data) { nassertv(has_element(n)); - _table[n]._data = std::move(data); + _table[n]._data = move(data); } #endif // USE_MOVE_SEMANTICS From 58c1581c0c7520311f72ba07e908f56e99efdf33 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 8 Jan 2017 17:20:17 -0500 Subject: [PATCH 65/70] Fix .whl version when no explicit --version is specified --- makepanda/makepanda.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 4faa683f87..ac528371c7 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -368,6 +368,9 @@ if VERSION is None: else: VERSION = ParsePandaVersion("dtool/PandaVersion.pp") +if WHLVERSION is None: + WHLVERSION = VERSION + print("Version: %s" % VERSION) if RUNTIME or RTDIST: print("Core API Version: %s" % COREAPI_VERSION) From 72a1a9820baf640fc9d06d6fd73f7f4785d4ce07 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 8 Jan 2017 17:50:48 -0500 Subject: [PATCH 66/70] Fix issues in ancient ffmpeg versions (Eg. Ubuntu Precise) --- panda/src/ffmpeg/ffmpegVideoCursor.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index 8e2d0b0e47..c9cee499cd 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -40,6 +40,10 @@ PStatCollector FfmpegVideoCursor::_export_frame_pcollector("*:FFMPEG Convert Vid #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO #endif +#if LIBAVCODEC_VERSION_MAJOR < 54 +#define AV_CODEC_ID_VP8 CODEC_ID_VP8 +#endif + #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 74, 100) #define AV_PIX_FMT_NONE PIX_FMT_NONE #define AV_PIX_FMT_BGR24 PIX_FMT_BGR24 @@ -116,6 +120,7 @@ init_from(FfmpegVideo *source) { _eof_known = false; _eof_frame = 0; +#if LIBAVUTIL_VERSION_MAJOR >= 52 // Check if we got an alpha format. Please note that some video codecs // (eg. libvpx) change the pix_fmt after decoding the first frame, which is // why we didn't do this earlier. @@ -123,7 +128,9 @@ init_from(FfmpegVideo *source) { if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) != 0) { _num_components = 4; _pixel_format = (int)AV_PIX_FMT_BGRA; - } else { + } else +#endif + { _num_components = 3; _pixel_format = (int)AV_PIX_FMT_BGR24; } From ba5bba42b019fdf35e34577ac839bc7a16cefa66 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 8 Jan 2017 17:51:09 -0500 Subject: [PATCH 67/70] Fix interrogate warnings, flesh out iterator header --- dtool/src/parser-inc/iterator | 72 ++++++++++++++++++++++++++++++++++- dtool/src/parser-inc/memory | 2 +- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/dtool/src/parser-inc/iterator b/dtool/src/parser-inc/iterator index 40b8e2f479..c6cdf654fa 100644 --- a/dtool/src/parser-inc/iterator +++ b/dtool/src/parser-inc/iterator @@ -1,6 +1,74 @@ #pragma once +#include +#include + namespace std { - template class iterator; - template class reverse_iterator; + // Iterator tags + struct input_iterator_tag {}; + struct output_iterator_tag {}; + struct forward_iterator_tag : public input_iterator_tag {}; + struct bidirectional_iterator_tag : public forward_iterator_tag {}; + struct random_access_iterator_tag : public bidirectional_iterator_tag {}; + + // Iterator traits + template struct iterator_traits { + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; + typedef typename Iterator::iterator_category iterator_category; + }; + + template struct iterator_traits { + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + typedef random_access_iterator_tag iterator_category; + }; + + template struct iterator_traits { + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + typedef random_access_iterator_tag iterator_category; + }; + + // Iterators + template struct iterator { + typedef T value_type; + typedef Distance difference_type; + typedef Pointer pointer; + typedef Reference reference; + typedef Category iterator_category; + }; + + template + class reverse_iterator : public + iterator::iterator_category, + typename iterator_traits::value_type, + typename iterator_traits::difference_type, + typename iterator_traits::pointer, + typename iterator_traits::reference> { + public: + typedef Iterator iterator_type; + typedef typename iterator_traits::difference_type difference_type; + typedef typename iterator_traits::reference reference; + typedef typename iterator_traits::pointer pointer; + }; + + template, + class Distance = ptrdiff_t> + class istream_iterator; + + template> + class ostream_iterator; + + template> + class istreambuf_iterator; + template > + class ostreambuf_iterator; }; diff --git a/dtool/src/parser-inc/memory b/dtool/src/parser-inc/memory index 30a54d006a..8c3a7b1b1d 100644 --- a/dtool/src/parser-inc/memory +++ b/dtool/src/parser-inc/memory @@ -122,7 +122,7 @@ namespace std { struct is_always_equal; template using rebind_alloc = size_t; - template using rebind_traits = allocator_traits >; + //template using rebind_traits = allocator_traits >; }; template class allocator; From 4ed199cece1843453cce95205ed1f9e3affa47e6 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 9 Jan 2017 18:45:23 +0100 Subject: [PATCH 68/70] Fix various compile warnings and a few code consistency issues --- direct/src/plugin/p3dInstance.cxx | 8 ++++---- direct/src/plugin/p3dOsxSplashWindow.cxx | 16 ++++++++-------- dtool/src/dtoolbase/dlmalloc_src.cxx | 9 +++++++-- .../interrogate/interfaceMakerPythonNative.cxx | 2 +- dtool/src/parser-inc/arpa/inet.h | 4 ++++ dtool/src/parser-inc/netdb.h | 9 +++++++++ panda/src/audiotraits/fmodAudioManager.cxx | 4 ++-- panda/src/audiotraits/openalAudioManager.cxx | 1 - panda/src/collide/collisionBox.cxx | 8 ++++---- panda/src/collide/collisionFloorMesh.cxx | 4 ++-- .../src/collide/collisionHandlerFluidPusher.cxx | 2 +- panda/src/collide/collisionInvSphere.cxx | 8 ++++---- panda/src/collide/collisionPlane.cxx | 14 +++++++------- panda/src/collide/collisionPolygon.cxx | 12 ++++++------ panda/src/collide/collisionSphere.cxx | 14 +++++++------- panda/src/collide/collisionTube.cxx | 10 +++++----- panda/src/downloader/httpClient.cxx | 2 +- panda/src/gobj/texture_ext.cxx | 4 ++-- panda/src/ode/odeTriMeshData.cxx | 2 +- panda/src/ode/odeTriMeshGeom.I | 2 +- panda/src/pgraph/clipPlaneAttrib.cxx | 4 ++-- panda/src/pgraph/portalClipper.cxx | 2 +- panda/src/physx/physxControllerDesc.h | 3 ++- pandatool/src/xfile/xParser.cxx.prebuilt | 2 +- pandatool/src/xfile/xParser.yxx | 2 +- 25 files changed, 83 insertions(+), 65 deletions(-) create mode 100644 dtool/src/parser-inc/arpa/inet.h create mode 100644 dtool/src/parser-inc/netdb.h diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index b3f96b3f9c..0eabdaafd5 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -3450,8 +3450,8 @@ paint_window_osx_port() { int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size()); size_t rowsize = _swbuffer->get_row_size(); - Rect src_rect = {0, 0, y_size, x_size}; - Rect ddrc_rect = {0, 0, y_size, x_size}; + Rect src_rect = {0, 0, (short)y_size, (short)x_size}; + Rect ddrc_rect = {0, 0, (short)y_size, (short)x_size}; QDErr err; @@ -3502,7 +3502,7 @@ paint_window_osx_cgcontext(CGContextRef context) { int y_size = min(_wparams.get_win_height(), _swbuffer->get_y_size()); if (_buffer_image != NULL) { - CGRect region = { { 0, 0 }, { x_size, y_size } }; + CGRect region = { { 0, 0 }, { (CGFloat)x_size, (CGFloat)y_size } }; CGContextDrawImage(context, region, _buffer_image); } } @@ -3538,7 +3538,7 @@ handle_event_osx_event_record(const P3D_event_data &event) { // First, convert the coordinates from screen coordinates to browser // window coordinates. WindowRef window = handle._handle._osx_cgcontext._window; - CGPoint cgpt = { pt.h, pt.v }; + CGPoint cgpt = { (CGFloat)pt.h, (CGFloat)pt.v }; HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL, kHICoordSpaceWindow, window); diff --git a/direct/src/plugin/p3dOsxSplashWindow.cxx b/direct/src/plugin/p3dOsxSplashWindow.cxx index 2014251149..c8fc969679 100644 --- a/direct/src/plugin/p3dOsxSplashWindow.cxx +++ b/direct/src/plugin/p3dOsxSplashWindow.cxx @@ -267,7 +267,7 @@ refresh() { return; } if (_toplevel_window != NULL) { - Rect r = { 0, 0, _win_height, _win_width }; + Rect r = { 0, 0, (short)_win_height, (short)_win_width }; InvalWindowRect(_toplevel_window, &r); } else { @@ -345,7 +345,7 @@ paint_window_osx_cgcontext(CGContextRef context) { CGColorSpaceRef rgb_space = CGColorSpaceCreateDeviceRGB(); CGColorRef bg = CGColorCreate(rgb_space, bg_components); - CGRect region = { { 0, 0 }, { _win_width, _win_height } }; + CGRect region = { { 0, 0 }, { (CGFloat)_win_width, (CGFloat)_win_height } }; CGContextSetFillColorWithColor(context, bg); CGContextFillRect(context, region); @@ -407,7 +407,7 @@ handle_event_osx_event_record(const P3D_event_data &event) { // First, convert the coordinates from screen coordinates to browser // window coordinates. WindowRef window = handle._handle._osx_cgcontext._window; - CGPoint cgpt = { pt.h, pt.v }; + CGPoint cgpt = { (CGFloat)pt.h, (CGFloat)pt.v }; HIPointConvert(&cgpt, kHICoordSpaceScreenPixel, NULL, kHICoordSpaceWindow, window); @@ -617,7 +617,7 @@ paint_progress_bar(CGContextRef context) { int bar_x, bar_y, bar_width, bar_height; get_bar_placement(bar_x, bar_y, bar_width, bar_height); - CGRect bar_rect = { { bar_x, bar_y }, { bar_width, bar_height } }; + CGRect bar_rect = { { (CGFloat)bar_x, (CGFloat)bar_y }, { (CGFloat)bar_width, (CGFloat)bar_height } }; // Clear the entire progress bar to white (or the background color). CGContextSetFillColorWithColor(context, bar_bg); @@ -627,7 +627,7 @@ paint_progress_bar(CGContextRef context) { if (_progress_known) { int progress_width = (int)(bar_width * _install_progress + 0.5); if (progress_width != 0) { - CGRect prog = { { bar_x, bar_y }, { progress_width, bar_height } }; + CGRect prog = { { (CGFloat)bar_x, (CGFloat)bar_y }, { (CGFloat)progress_width, (CGFloat)bar_height } }; CGContextSetFillColorWithColor(context, bar); CGContextFillRect(context, prog); } @@ -642,7 +642,7 @@ paint_progress_bar(CGContextRef context) { progress = block_travel * 2 - progress; } - CGRect prog = { { bar_x + progress, bar_y }, { block_width, bar_height } }; + CGRect prog = { { (CGFloat)(bar_x + progress), (CGFloat)bar_y }, { (CGFloat)block_width, (CGFloat)bar_height } }; CGContextSetFillColorWithColor(context, bar); CGContextFillRect(context, prog); } @@ -652,8 +652,8 @@ paint_progress_bar(CGContextRef context) { // We offset the border by half a pixel, so we'll be drawing the one-pixel // line through the middle of a pixel, and it won't try to antialias // itself into a half-black two-pixel line. - CGRect border_rect = { { bar_x - 0.5, bar_y - 0.5 }, - { bar_width + 1, bar_height + 1 } }; + CGRect border_rect = { { (CGFloat)(bar_x - 0.5), (CGFloat)(bar_y - 0.5) }, + { (CGFloat)(bar_width + 1), (CGFloat)(bar_height + 1) } }; CGContextBeginPath(context); CGContextSetLineWidth(context, 1); diff --git a/dtool/src/dtoolbase/dlmalloc_src.cxx b/dtool/src/dtoolbase/dlmalloc_src.cxx index 008350de73..a26fcd28cd 100644 --- a/dtool/src/dtoolbase/dlmalloc_src.cxx +++ b/dtool/src/dtoolbase/dlmalloc_src.cxx @@ -587,8 +587,11 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP #define MAX_SIZE_T (~(size_t)0) #ifndef USE_LOCKS /* ensure true if spin or recursive locks set */ -#define USE_LOCKS ((defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || \ - (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0)) +#if (defined(USE_SPIN_LOCKS) && USE_SPIN_LOCKS != 0) || (defined(USE_RECURSIVE_LOCKS) && USE_RECURSIVE_LOCKS != 0) +#define USE_LOCKS 1 +#else +#define USE_LOCKS 0 +#endif #endif /* USE_LOCKS */ #if USE_LOCKS /* Spin locks for gcc >= 4.1, older gcc on x86, MSC >= 1310 */ @@ -647,7 +650,9 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP #ifndef HAVE_MREMAP #ifdef linux #define HAVE_MREMAP 1 +#ifndef _GNU_SOURCE #define _GNU_SOURCE /* Turns on mremap() definition */ +#endif #else /* linux */ #define HAVE_MREMAP 0 #endif /* linux */ diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index a844771fa6..f24839d331 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -6198,7 +6198,7 @@ write_make_seq(ostream &out, Object *obj, const std::string &ClassName, // the assumption that the called method doesn't do anything with this // tuple other than unpack it (which is a fairly safe assumption to make). out << " PyTupleObject args;\n"; - out << " PyObject_INIT_VAR(&args, &PyTuple_Type, 1);\n"; + out << " (void)PyObject_INIT_VAR(&args, &PyTuple_Type, 1);\n"; } out << diff --git a/dtool/src/parser-inc/arpa/inet.h b/dtool/src/parser-inc/arpa/inet.h new file mode 100644 index 0000000000..a3ed68c461 --- /dev/null +++ b/dtool/src/parser-inc/arpa/inet.h @@ -0,0 +1,4 @@ +#pragma once + +#include +#include diff --git a/dtool/src/parser-inc/netdb.h b/dtool/src/parser-inc/netdb.h new file mode 100644 index 0000000000..367025cd3a --- /dev/null +++ b/dtool/src/parser-inc/netdb.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include + +struct hostent; +struct netent; +struct protoent; +struct servent; diff --git a/panda/src/audiotraits/fmodAudioManager.cxx b/panda/src/audiotraits/fmodAudioManager.cxx index 7d7ae246e3..dc98e76287 100644 --- a/panda/src/audiotraits/fmodAudioManager.cxx +++ b/panda/src/audiotraits/fmodAudioManager.cxx @@ -424,8 +424,8 @@ get_sound(const string &file_name, bool positional, int) { vfs->resolve_filename(path, get_model_path()); // Build a new AudioSound from the audio data. - PT(AudioSound) audioSound = 0; - PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, path, positional ); + PT(AudioSound) audioSound; + PT(FmodAudioSound) fmodAudioSound = new FmodAudioSound(this, path, positional); _all_sounds.insert(fmodAudioSound); diff --git a/panda/src/audiotraits/openalAudioManager.cxx b/panda/src/audiotraits/openalAudioManager.cxx index ba1b4684a3..b6d68a0ec0 100644 --- a/panda/src/audiotraits/openalAudioManager.cxx +++ b/panda/src/audiotraits/openalAudioManager.cxx @@ -1022,7 +1022,6 @@ cleanup() { OpenALAudioManager::SoundData:: SoundData() : _manager(0), - _movie(0), _sample(0), _stream(NULL), _length(0.0), diff --git a/panda/src/collide/collisionBox.cxx b/panda/src/collide/collisionBox.cxx index b358d8b359..b55988c352 100644 --- a/panda/src/collide/collisionBox.cxx +++ b/panda/src/collide/collisionBox.cxx @@ -199,7 +199,7 @@ PT(CollisionEntry) CollisionBox:: test_intersection_from_sphere(const CollisionEntry &entry) const { const CollisionSphere *sphere; - DCAST_INTO_R(sphere, entry.get_from(), 0); + DCAST_INTO_R(sphere, entry.get_from(), NULL); CPT(TransformState) wrt_space = entry.get_wrt_space(); CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space(); @@ -402,7 +402,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionBox:: test_intersection_from_ray(const CollisionEntry &entry) const { const CollisionRay *ray; - DCAST_INTO_R(ray, entry.get_from(), 0); + DCAST_INTO_R(ray, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); LPoint3 from_origin = ray->get_origin() * wrt_mat; @@ -483,7 +483,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionBox:: test_intersection_from_segment(const CollisionEntry &entry) const { const CollisionSegment *seg; - DCAST_INTO_R(seg, entry.get_from(), 0); + DCAST_INTO_R(seg, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); LPoint3 from_origin = seg->get_point_a() * wrt_mat; @@ -564,7 +564,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionBox:: test_intersection_from_box(const CollisionEntry &entry) const { const CollisionBox *box; - DCAST_INTO_R(box, entry.get_from(), 0); + DCAST_INTO_R(box, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); diff --git a/panda/src/collide/collisionFloorMesh.cxx b/panda/src/collide/collisionFloorMesh.cxx index fcec727778..d523875727 100644 --- a/panda/src/collide/collisionFloorMesh.cxx +++ b/panda/src/collide/collisionFloorMesh.cxx @@ -125,7 +125,7 @@ compute_internal_bounds() const { PT(CollisionEntry) CollisionFloorMesh:: test_intersection_from_ray(const CollisionEntry &entry) const { const CollisionRay *ray; - DCAST_INTO_R(ray, entry.get_from(), 0); + DCAST_INTO_R(ray, entry.get_from(), NULL); LPoint3 from_origin = ray->get_origin() * entry.get_wrt_mat(); double fx = from_origin[0]; @@ -190,7 +190,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionFloorMesh:: test_intersection_from_sphere(const CollisionEntry &entry) const { const CollisionSphere *sphere; - DCAST_INTO_R(sphere, entry.get_from(), 0); + DCAST_INTO_R(sphere, entry.get_from(), NULL); LPoint3 from_origin = sphere->get_center() * entry.get_wrt_mat(); double fx = from_origin[0]; diff --git a/panda/src/collide/collisionHandlerFluidPusher.cxx b/panda/src/collide/collisionHandlerFluidPusher.cxx index eea0cc1f22..0a48381d01 100644 --- a/panda/src/collide/collisionHandlerFluidPusher.cxx +++ b/panda/src/collide/collisionHandlerFluidPusher.cxx @@ -136,7 +136,7 @@ handle_entries() { // currently we only support spheres as the collider const CollisionSphere *sphere; - DCAST_INTO_R(sphere, entries.front()->get_from(), 0); + DCAST_INTO_R(sphere, entries.front()->get_from(), false); from_node_path.set_pos(wrt_node, 0,0,0); LPoint3 sphere_offset = (sphere->get_center() * diff --git a/panda/src/collide/collisionInvSphere.cxx b/panda/src/collide/collisionInvSphere.cxx index 913ef32589..35a73225dd 100644 --- a/panda/src/collide/collisionInvSphere.cxx +++ b/panda/src/collide/collisionInvSphere.cxx @@ -92,7 +92,7 @@ compute_internal_bounds() const { PT(CollisionEntry) CollisionInvSphere:: test_intersection_from_sphere(const CollisionEntry &entry) const { const CollisionSphere *sphere; - DCAST_INTO_R(sphere, entry.get_from(), 0); + DCAST_INTO_R(sphere, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -144,7 +144,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionInvSphere:: test_intersection_from_line(const CollisionEntry &entry) const { const CollisionLine *line; - DCAST_INTO_R(line, entry.get_from(), 0); + DCAST_INTO_R(line, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -185,7 +185,7 @@ test_intersection_from_line(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionInvSphere:: test_intersection_from_ray(const CollisionEntry &entry) const { const CollisionRay *ray; - DCAST_INTO_R(ray, entry.get_from(), 0); + DCAST_INTO_R(ray, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -228,7 +228,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionInvSphere:: test_intersection_from_segment(const CollisionEntry &entry) const { const CollisionSegment *segment; - DCAST_INTO_R(segment, entry.get_from(), 0); + DCAST_INTO_R(segment, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); diff --git a/panda/src/collide/collisionPlane.cxx b/panda/src/collide/collisionPlane.cxx index c551464960..d722adde7b 100644 --- a/panda/src/collide/collisionPlane.cxx +++ b/panda/src/collide/collisionPlane.cxx @@ -107,7 +107,7 @@ compute_internal_bounds() const { PT(CollisionEntry) CollisionPlane:: test_intersection_from_sphere(const CollisionEntry &entry) const { const CollisionSphere *sphere; - DCAST_INTO_R(sphere, entry.get_from(), 0); + DCAST_INTO_R(sphere, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -146,7 +146,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionPlane:: test_intersection_from_line(const CollisionEntry &entry) const { const CollisionLine *line; - DCAST_INTO_R(line, entry.get_from(), 0); + DCAST_INTO_R(line, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -191,7 +191,7 @@ test_intersection_from_line(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionPlane:: test_intersection_from_ray(const CollisionEntry &entry) const { const CollisionRay *ray; - DCAST_INTO_R(ray, entry.get_from(), 0); + DCAST_INTO_R(ray, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -243,7 +243,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionPlane:: test_intersection_from_segment(const CollisionEntry &entry) const { const CollisionSegment *segment; - DCAST_INTO_R(segment, entry.get_from(), 0); + DCAST_INTO_R(segment, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -300,7 +300,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionPlane:: test_intersection_from_tube(const CollisionEntry &entry) const { const CollisionTube *tube; - DCAST_INTO_R(tube, entry.get_from(), 0); + DCAST_INTO_R(tube, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -371,7 +371,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionPlane:: test_intersection_from_parabola(const CollisionEntry &entry) const { const CollisionParabola *parabola; - DCAST_INTO_R(parabola, entry.get_from(), 0); + DCAST_INTO_R(parabola, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -437,7 +437,7 @@ test_intersection_from_parabola(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionPlane:: test_intersection_from_box(const CollisionEntry &entry) const { const CollisionBox *box; - DCAST_INTO_R(box, entry.get_from(), 0); + DCAST_INTO_R(box, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); diff --git a/panda/src/collide/collisionPolygon.cxx b/panda/src/collide/collisionPolygon.cxx index ff64dcc298..646a7b9439 100644 --- a/panda/src/collide/collisionPolygon.cxx +++ b/panda/src/collide/collisionPolygon.cxx @@ -364,7 +364,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { } const CollisionSphere *sphere; - DCAST_INTO_R(sphere, entry.get_from(), 0); + DCAST_INTO_R(sphere, entry.get_from(), NULL); CPT(TransformState) wrt_space = entry.get_wrt_space(); CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space(); @@ -545,7 +545,7 @@ test_intersection_from_line(const CollisionEntry &entry) const { } const CollisionLine *line; - DCAST_INTO_R(line, entry.get_from(), 0); + DCAST_INTO_R(line, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -613,7 +613,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { } const CollisionRay *ray; - DCAST_INTO_R(ray, entry.get_from(), 0); + DCAST_INTO_R(ray, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -686,7 +686,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const { } const CollisionSegment *segment; - DCAST_INTO_R(segment, entry.get_from(), 0); + DCAST_INTO_R(segment, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -761,7 +761,7 @@ test_intersection_from_parabola(const CollisionEntry &entry) const { } const CollisionParabola *parabola; - DCAST_INTO_R(parabola, entry.get_from(), 0); + DCAST_INTO_R(parabola, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -846,7 +846,7 @@ test_intersection_from_parabola(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionPolygon:: test_intersection_from_box(const CollisionEntry &entry) const { const CollisionBox *box; - DCAST_INTO_R(box, entry.get_from(), 0); + DCAST_INTO_R(box, entry.get_from(), NULL); // To make things easier, transform the box into the coordinate space of the // plane. diff --git a/panda/src/collide/collisionSphere.cxx b/panda/src/collide/collisionSphere.cxx index 2e0802b350..139a39a4b1 100644 --- a/panda/src/collide/collisionSphere.cxx +++ b/panda/src/collide/collisionSphere.cxx @@ -120,7 +120,7 @@ compute_internal_bounds() const { PT(CollisionEntry) CollisionSphere:: test_intersection_from_sphere(const CollisionEntry &entry) const { const CollisionSphere *sphere; - DCAST_INTO_R(sphere, entry.get_from(), 0); + DCAST_INTO_R(sphere, entry.get_from(), NULL); CPT(TransformState) wrt_space = entry.get_wrt_space(); @@ -231,7 +231,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionSphere:: test_intersection_from_line(const CollisionEntry &entry) const { const CollisionLine *line; - DCAST_INTO_R(line, entry.get_from(), 0); + DCAST_INTO_R(line, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -271,7 +271,7 @@ test_intersection_from_line(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionSphere:: test_intersection_from_box(const CollisionEntry &entry) const { const CollisionBox *box; - DCAST_INTO_R(box, entry.get_from(), 0); + DCAST_INTO_R(box, entry.get_from(), NULL); // Instead of transforming the box into the sphere's coordinate space, we do // it the other way around. It's easier that way. @@ -347,7 +347,7 @@ test_intersection_from_box(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionSphere:: test_intersection_from_ray(const CollisionEntry &entry) const { const CollisionRay *ray; - DCAST_INTO_R(ray, entry.get_from(), 0); + DCAST_INTO_R(ray, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -394,7 +394,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionSphere:: test_intersection_from_segment(const CollisionEntry &entry) const { const CollisionSegment *segment; - DCAST_INTO_R(segment, entry.get_from(), 0); + DCAST_INTO_R(segment, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -443,7 +443,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionSphere:: test_intersection_from_tube(const CollisionEntry &entry) const { const CollisionTube *tube; - DCAST_INTO_R(tube, entry.get_from(), 0); + DCAST_INTO_R(tube, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -499,7 +499,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionSphere:: test_intersection_from_parabola(const CollisionEntry &entry) const { const CollisionParabola *parabola; - DCAST_INTO_R(parabola, entry.get_from(), 0); + DCAST_INTO_R(parabola, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); diff --git a/panda/src/collide/collisionTube.cxx b/panda/src/collide/collisionTube.cxx index cb3f24f737..8e3b188aab 100644 --- a/panda/src/collide/collisionTube.cxx +++ b/panda/src/collide/collisionTube.cxx @@ -146,7 +146,7 @@ compute_internal_bounds() const { PT(CollisionEntry) CollisionTube:: test_intersection_from_sphere(const CollisionEntry &entry) const { const CollisionSphere *sphere; - DCAST_INTO_R(sphere, entry.get_from(), 0); + DCAST_INTO_R(sphere, entry.get_from(), NULL); CPT(TransformState) wrt_space = entry.get_wrt_space(); CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space(); @@ -224,7 +224,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionTube:: test_intersection_from_line(const CollisionEntry &entry) const { const CollisionLine *line; - DCAST_INTO_R(line, entry.get_from(), 0); + DCAST_INTO_R(line, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -272,7 +272,7 @@ test_intersection_from_line(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionTube:: test_intersection_from_ray(const CollisionEntry &entry) const { const CollisionRay *ray; - DCAST_INTO_R(ray, entry.get_from(), 0); + DCAST_INTO_R(ray, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -333,7 +333,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionTube:: test_intersection_from_segment(const CollisionEntry &entry) const { const CollisionSegment *segment; - DCAST_INTO_R(segment, entry.get_from(), 0); + DCAST_INTO_R(segment, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); @@ -397,7 +397,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const { PT(CollisionEntry) CollisionTube:: test_intersection_from_parabola(const CollisionEntry &entry) const { const CollisionParabola *parabola; - DCAST_INTO_R(parabola, entry.get_from(), 0); + DCAST_INTO_R(parabola, entry.get_from(), NULL); const LMatrix4 &wrt_mat = entry.get_wrt_mat(); diff --git a/panda/src/downloader/httpClient.cxx b/panda/src/downloader/httpClient.cxx index 63ba1c6258..129d5fb6be 100644 --- a/panda/src/downloader/httpClient.cxx +++ b/panda/src/downloader/httpClient.cxx @@ -807,7 +807,7 @@ load_client_certificate() { // Rewind the "file" to the beginning in order to read the public key // (which might appear first in the file). - BIO_reset(mbio); + (void)BIO_reset(mbio); ERR_clear_error(); _client_certificate_pub = diff --git a/panda/src/gobj/texture_ext.cxx b/panda/src/gobj/texture_ext.cxx index 1e661e960a..507fa41fc4 100644 --- a/panda/src/gobj/texture_ext.cxx +++ b/panda/src/gobj/texture_ext.cxx @@ -66,7 +66,7 @@ set_ram_image(PyObject *image, Texture::CompressionMode compression, if (view.len % component_width != 0) { PyErr_Format(PyExc_ValueError, - "byte buffer is not a multiple of %zu bytes", + "byte buffer is not a multiple of %d bytes", component_width); return; } @@ -131,7 +131,7 @@ set_ram_image_as(PyObject *image, const string &provided_format) { if (view.len % component_width != 0) { PyErr_Format(PyExc_ValueError, - "byte buffer is not a multiple of %zu bytes", + "byte buffer is not a multiple of %d bytes", component_width); return; } diff --git a/panda/src/ode/odeTriMeshData.cxx b/panda/src/ode/odeTriMeshData.cxx index afae75b753..5f02cefa56 100644 --- a/panda/src/ode/odeTriMeshData.cxx +++ b/panda/src/ode/odeTriMeshData.cxx @@ -29,7 +29,7 @@ get_data(dGeomID id) { if (iter != data_map.end()) { return iter->second; } - return 0; + return NULL; } void OdeTriMeshData:: diff --git a/panda/src/ode/odeTriMeshGeom.I b/panda/src/ode/odeTriMeshGeom.I index 8bfd233bbf..b0a2e6177c 100644 --- a/panda/src/ode/odeTriMeshGeom.I +++ b/panda/src/ode/odeTriMeshGeom.I @@ -34,7 +34,7 @@ set_tri_mesh_data(OdeTriMeshData &data) { INLINE PT(OdeTriMeshData) OdeTriMeshGeom:: get_tri_mesh_data() const { - nassertr(_id != 0 ,0); + nassertr(_id != 0, NULL); return OdeTriMeshData::get_data(_id); } diff --git a/panda/src/pgraph/clipPlaneAttrib.cxx b/panda/src/pgraph/clipPlaneAttrib.cxx index e62a3d6e24..c95f9437c4 100644 --- a/panda/src/pgraph/clipPlaneAttrib.cxx +++ b/panda/src/pgraph/clipPlaneAttrib.cxx @@ -487,7 +487,7 @@ filter_to_max(int max_clip_planes) const { CPT(RenderAttrib) ClipPlaneAttrib:: compose_off(const RenderAttrib *other) const { const ClipPlaneAttrib *ta; - DCAST_INTO_R(ta, other, 0); + DCAST_INTO_R(ta, other, NULL); if (_off_all_planes || (!ta->_off_all_planes && ta->_off_planes.empty())) { // If we turn off all planes, or the other turns none off, the result is @@ -701,7 +701,7 @@ get_hash_impl() const { CPT(RenderAttrib) ClipPlaneAttrib:: compose_impl(const RenderAttrib *other) const { const ClipPlaneAttrib *ta; - DCAST_INTO_R(ta, other, 0); + DCAST_INTO_R(ta, other, NULL); if (ta->_off_all_planes) { // If the other type turns off all planes, it doesn't matter what we are. diff --git a/panda/src/pgraph/portalClipper.cxx b/panda/src/pgraph/portalClipper.cxx index 7b9e55556b..f6d45aab8f 100644 --- a/panda/src/pgraph/portalClipper.cxx +++ b/panda/src/pgraph/portalClipper.cxx @@ -39,7 +39,7 @@ PortalClipper:: PortalClipper(GeometricBoundingVolume *frustum, SceneSetup *scene_setup): _reduced_viewport_min(-1,-1), _reduced_viewport_max(1,1), -_clip_state(0) +_clip_state(NULL) { _previous = new GeomNode("my_frustum"); diff --git a/panda/src/physx/physxControllerDesc.h b/panda/src/physx/physxControllerDesc.h index 7919b60118..4624938ffd 100644 --- a/panda/src/physx/physxControllerDesc.h +++ b/panda/src/physx/physxControllerDesc.h @@ -23,8 +23,9 @@ * Descriptor class for a character controller. */ class EXPCL_PANDAPHYSX PhysxControllerDesc { - PUBLISHED: + virtual ~PhysxControllerDesc() {}; + virtual void set_to_default() = 0; virtual bool is_valid() const = 0; diff --git a/pandatool/src/xfile/xParser.cxx.prebuilt b/pandatool/src/xfile/xParser.cxx.prebuilt index 606ead1db3..42c65a72a6 100644 --- a/pandatool/src/xfile/xParser.cxx.prebuilt +++ b/pandatool/src/xfile/xParser.cxx.prebuilt @@ -98,7 +98,7 @@ static XFile *x_file = (XFile *)NULL; static XFileNode *current_node = (XFileNode *)NULL; -static PT(XFileDataDef) current_data_def = (XFileDataDef *)NULL; +static PT(XFileDataDef) current_data_def; //////////////////////////////////////////////////////////////////// // Defining the interface to the parser. diff --git a/pandatool/src/xfile/xParser.yxx b/pandatool/src/xfile/xParser.yxx index 4aa8ffd3b3..a98f39d177 100644 --- a/pandatool/src/xfile/xParser.yxx +++ b/pandatool/src/xfile/xParser.yxx @@ -32,7 +32,7 @@ static XFile *x_file = (XFile *)NULL; static XFileNode *current_node = (XFileNode *)NULL; -static PT(XFileDataDef) current_data_def = (XFileDataDef *)NULL; +static PT(XFileDataDef) current_data_def; //////////////////////////////////////////////////////////////////// // Defining the interface to the parser. From 43a5f2a9f20118db9fcbeec14467c97a711d37b6 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 9 Jan 2017 20:38:33 +0100 Subject: [PATCH 69/70] Fixes for Python 3.5: - Disable conversion to Windows newlines, which is causing double Windows newlines for Config.prc - We need to copy vcruntime140.dll to the bin directory for Python 3.5+ build using MSVC 2010 to work --- makepanda/makepanda.py | 6 +++--- makepanda/makepandacore.py | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index ac528371c7..6a7d8ce521 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2887,8 +2887,8 @@ if tp_dir is not None: pydll += ".dll" CopyFile(GetOutputDir() + "/bin" + pydll, SDK["PYTHON"] + pydll) - #for fn in glob.glob(SDK["PYTHON"] + "/vcruntime*.dll"): - # CopyFile(GetOutputDir() + "/bin/", fn) + for fn in glob.glob(SDK["PYTHON"] + "/vcruntime*.dll"): + CopyFile(GetOutputDir() + "/bin/", fn) # Copy the whole Python directory. CopyTree(GetOutputDir() + "/python", SDK["PYTHON"]) @@ -2907,7 +2907,7 @@ if tp_dir is not None: else: idents = () - for ident in tree.findall('./{urn:schemas-microsoft-com:asm.v1}dependency/{urn:schemas-microsoft-com:asm.v1}dependentAssembly/{urn:schemas-microsoft-com:asm.v1}assemblyIdentity'): + for ident in idents: sxs_name = '_'.join([ ident.get('processorArchitecture'), ident.get('name').lower(), diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index ee903a3940..24f3614337 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -980,7 +980,10 @@ def WriteFile(wfile, data, newline=None): data = data.replace('\n', newline) try: - dsthandle = open(wfile, "w") + if sys.version_info >= (3, 0): + dsthandle = open(wfile, "w", newline='') + else: + dsthandle = open(wfile, "w") dsthandle.write(data) dsthandle.close() except: From 749e09d49ecc31a5235a4af46849626b483f5936 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 9 Jan 2017 23:10:51 +0100 Subject: [PATCH 70/70] ffmpeg: don't hide last frame of video This is not quite a complete fix, since the last frame of the video won't be shown long enough for it to matter when looping the video. A more complete fix may be needed later. --- panda/src/ffmpeg/ffmpegVideoCursor.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/panda/src/ffmpeg/ffmpegVideoCursor.cxx b/panda/src/ffmpeg/ffmpegVideoCursor.cxx index c9cee499cd..8a23853811 100644 --- a/panda/src/ffmpeg/ffmpegVideoCursor.cxx +++ b/panda/src/ffmpeg/ffmpegVideoCursor.cxx @@ -327,13 +327,13 @@ set_time(double timestamp, int loop_count) { if (_eof_known) { if (loop_count == 0) { - frame = frame % _eof_frame; + frame = frame % (_eof_frame + 1); } else { - int last_frame = _eof_frame * loop_count; + int last_frame = (_eof_frame + 1) * loop_count; if (frame < last_frame) { - frame = frame % _eof_frame; + frame = frame % (_eof_frame + 1); } else { - frame = _eof_frame - 1; + frame = _eof_frame; } } }