Explorar o código

Merge branch 'release/1.10.x'

rdb %!s(int64=6) %!d(string=hai) anos
pai
achega
b78b7be326

+ 6 - 3
README.md

@@ -185,16 +185,19 @@ from the Play Store.  Many of the dependencies can be installed by running the
 following command in the Termux shell:
 
 ```bash
-pkg install python-dev termux-tools ndk-stl ndk-sysroot clang libvorbis-dev libopus-dev opusfile-dev openal-soft-dev freetype-dev harfbuzz-dev libpng-dev ecj4.6 dx patchelf aapt apksigner libcrypt-dev
+pkg install python ndk-sysroot clang bison freetype harfbuzz libpng eigen openal-soft opusfile libvorbis assimp libopus ecj dx patchelf aapt apksigner libcrypt openssl pkg-config
 ```
 
-Then, you can build and install the .apk right away using these commands:
+Then, you can build the .apk using this command:
 
 ```bash
 python makepanda/makepanda.py --everything --target android-21 --no-tiff --installer
-xdg-open panda3d.apk
 ```
 
+You can install the generated panda3d.apk by browsing to the panda3d folder
+using a file manager.  You may need to copy it to `/sdcard` to be able to
+access it from other apps.
+
 To launch a Python program from Termux, you can use the `run_python.sh` script
 inside the `panda/src/android` directory.  It will launch Python in a separate
 activity, load it with the Python script you passed as argument, and use a

+ 4 - 0
direct/src/actor/Actor.py

@@ -5,6 +5,7 @@ __all__ = ['Actor']
 from panda3d.core import *
 from panda3d.core import Loader as PandaLoader
 from direct.showbase.DirectObject import DirectObject
+from direct.showbase.Loader import Loader
 from direct.directnotify import DirectNotifyGlobal
 
 
@@ -1886,6 +1887,9 @@ class Actor(DirectObject, NodePath):
                 else:
                     loaderOptions.setFlags(loaderOptions.getFlags() | LoaderOptions.LFReportErrors)
 
+            # Ensure that custom Python loader hooks are initialized.
+            Loader._loadPythonFileTypes()
+
             # Pass loaderOptions to specify that we want to
             # get the skeleton model.  This only matters to model
             # files (like .mb) for which we can choose to extract

+ 3 - 3
direct/src/dcparser/dcPackerInterface.I

@@ -253,8 +253,9 @@ do_unpack_int64(const char *buffer) {
                     ((uint64_t)(unsigned char)buffer[4] << 32) |
                     ((uint64_t)(unsigned char)buffer[5] << 40) |
                     ((uint64_t)(unsigned char)buffer[6] << 48) |
-                    ((int64_t)(signed char)buffer[7] << 54));
+                    ((int64_t)(signed char)buffer[7] << 56));
 }
+
 /**
  *
  */
@@ -295,10 +296,9 @@ do_unpack_uint64(const char *buffer) {
           ((uint64_t)(unsigned char)buffer[4] << 32) |
           ((uint64_t)(unsigned char)buffer[5] << 40) |
           ((uint64_t)(unsigned char)buffer[6] << 48) |
-          ((int64_t)(signed char)buffer[7] << 54));
+          ((uint64_t)(unsigned char)buffer[7] << 56));
 }
 
-
 /**
  *
  */

+ 0 - 1
direct/src/dcparser/dcPackerInterface.h

@@ -16,7 +16,6 @@
 
 #include "dcbase.h"
 #include "dcSubatomicType.h"
-#include "vector_uchar.h"
 
 class DCFile;
 class DCField;

+ 0 - 1
direct/src/dcparser/dcParserDefs.h

@@ -16,7 +16,6 @@
 
 #include "dcbase.h"
 #include "dcSubatomicType.h"
-#include "vector_uchar.h"
 
 class DCFile;
 class DCClass;

+ 4 - 0
direct/src/dcparser/dcbase.h

@@ -32,6 +32,7 @@
 #include "pvector.h"
 #include "pmap.h"
 #include "pset.h"
+#include "vector_uchar.h"
 
 #else  // WITHIN_PANDA
 
@@ -81,6 +82,7 @@
 #define nassertr_always(condition, return_value) assert(condition)
 #define nassertv(condition) assert(condition)
 #define nassertv_always(condition) assert(condition)
+#define nassert_raise(message) {std::cerr << message << std::endl; abort();}
 
 // Panda defines a special Filename class.  We'll use an ordinary string
 // instead.
@@ -97,8 +99,10 @@ typedef std::string Filename;
 #define pvector std::vector
 #define pmap std::map
 #define pset std::set
+#define vector_uchar std::vector<unsigned char>
 
 #include <stdint.h>
+#include <string.h>
 
 typedef std::ifstream pifstream;
 typedef std::ofstream pofstream;

+ 0 - 1
direct/src/dcparser/hashGenerator.h

@@ -16,7 +16,6 @@
 
 #include "dcbase.h"
 #include "primeNumberGenerator.h"
-#include "vector_uchar.h"
 
 /**
  * This class generates an arbitrary hash number from a sequence of ints.

+ 13 - 3
direct/src/showbase/Loader.py

@@ -22,6 +22,8 @@ class Loader(DirectObject):
     notify = directNotify.newCategory("Loader")
     loaderIndex = 0
 
+    _loadedPythonFileTypes = False
+
     class Callback:
         """Returned by loadModel when used asynchronously.  This class is
         modelled after Future, and can be awaited."""
@@ -149,8 +151,7 @@ class Loader(DirectObject):
         Loader.loaderIndex += 1
         self.accept(self.hook, self.__gotAsyncObject)
 
-        if ConfigVariableBool('loader-support-entry-points', True):
-            self._loadPythonFileTypes()
+        self._loadPythonFileTypes()
 
     def destroy(self):
         self.ignore(self.hook)
@@ -158,7 +159,14 @@ class Loader(DirectObject):
         del self.base
         del self.loader
 
-    def _loadPythonFileTypes(self):
+    @classmethod
+    def _loadPythonFileTypes(cls):
+        if cls._loadedPythonFileTypes:
+            return
+
+        if not ConfigVariableBool('loader-support-entry-points', True):
+            return
+
         import importlib
         try:
             pkg_resources = importlib.import_module('pkg_resources')
@@ -171,6 +179,8 @@ class Loader(DirectObject):
             for entry_point in pkg_resources.iter_entry_points('panda3d.loaders'):
                 registry.register_deferred_type(entry_point)
 
+            cls._loadedPythonFileTypes = True
+
     # model loading funcs
     def loadModel(self, modelPath, loaderOptions = None, noCache = None,
                   allowInstance = False, okMissing = None,

+ 5 - 2
direct/src/stdpy/threading.py

@@ -87,7 +87,7 @@ class Thread(ThreadBase):
     object.  The wrapper is designed to emulate Python's own
     threading.Thread object. """
 
-    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
+    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}, daemon=None):
         ThreadBase.__init__(self)
 
         assert group is None
@@ -99,7 +99,10 @@ class Thread(ThreadBase):
             name = _newname()
 
         current = current_thread()
-        self.__dict__['daemon'] = current.daemon
+        if daemon is not None:
+            self.__dict__['daemon'] = daemon
+        else:
+            self.__dict__['daemon'] = current.daemon
         self.__dict__['name'] = name
 
         def call_run():

+ 22 - 3
direct/src/stdpy/threading2.py

@@ -14,6 +14,7 @@ module, and so it is therefore layered on top of Panda's thread
 implementation. """
 
 import sys as _sys
+import atexit as _atexit
 
 from direct.stdpy import thread as _thread
 from direct.stdpy.thread import stack_size, _newname, _local as local
@@ -395,8 +396,12 @@ class Thread(_Verbose):
     # operation on/with a NoneType
     __exc_info = _sys.exc_info
 
+    # Set to True when the _shutdown handler is registered as atexit function.
+    # Protected by _active_limbo_lock.
+    __registered_atexit = False
+
     def __init__(self, group=None, target=None, name=None,
-                 args=(), kwargs=None, verbose=None):
+                 args=(), kwargs=None, verbose=None, daemon=None):
         assert group is None, "group argument must be None for now"
         _Verbose.__init__(self, verbose)
         if kwargs is None:
@@ -405,7 +410,10 @@ class Thread(_Verbose):
         self.__name = str(name or _newname())
         self.__args = args
         self.__kwargs = kwargs
-        self.__daemonic = self._set_daemon()
+        if daemon is not None:
+            self.__daemonic = daemon
+        else:
+            self.__daemonic = self._set_daemon()
         self.__started = False
         self.__stopped = False
         self.__block = Condition(Lock())
@@ -436,6 +444,14 @@ class Thread(_Verbose):
             self._note("%s.start(): starting thread", self)
         _active_limbo_lock.acquire()
         _limbo[self] = self
+
+        # If we are starting a non-daemon thread, we need to call join() on it
+        # when the interpreter exits.  Python will call _shutdown() on the
+        # built-in threading module automatically, but not on our module.
+        if not self.__daemonic and not Thread.__registered_atexit:
+            _atexit.register(_shutdown)
+            Thread.__registered_atexit = True
+
         _active_limbo_lock.release()
         _start_new_thread(self.__bootstrap, ())
         self.__started = True
@@ -599,6 +615,9 @@ class Thread(_Verbose):
         assert not self.__started, "cannot set daemon status of active thread"
         self.__daemonic = daemonic
 
+    name = property(getName, setName)
+    daemon = property(isDaemon, setDaemon)
+
 # The timer class was contributed by Itamar Shtull-Trauring
 
 def Timer(*args, **kwargs):
@@ -670,7 +689,7 @@ class _MainThread(Thread):
 class _DummyThread(Thread):
 
     def __init__(self):
-        Thread.__init__(self, name=_newname("Dummy-%d"))
+        Thread.__init__(self, name=_newname("Dummy-%d"), daemon=True)
 
         # Thread.__block consumes an OS-level locking primitive, which
         # can never be used by a _DummyThread.  Since a _DummyThread

+ 3 - 6
dtool/src/interrogatedb/py_compat.h

@@ -141,16 +141,13 @@ typedef long Py_hash_t;
 
 #if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_CallNoArg)
 INLINE PyObject *_PyObject_CallNoArg(PyObject *func) {
-  static PyTupleObject empty_tuple = {PyVarObject_HEAD_INIT(nullptr, 0)};
-#ifdef Py_TRACE_REFS
-  _Py_AddToAllObjects((PyObject *)&empty_tuple, 0);
-#endif
-  return PyObject_Call(func, (PyObject *)&empty_tuple, nullptr);
+  static PyObject *empty_tuple = PyTuple_New(0);
+  return PyObject_Call(func, empty_tuple, nullptr);
 }
 #  define _PyObject_CallNoArg _PyObject_CallNoArg
 #endif
 
-#ifndef _PyObject_FastCall
+#if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_FastCall)
 INLINE PyObject *_PyObject_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs) {
   PyObject *tuple = PyTuple_New(nargs);
   for (Py_ssize_t i = 0; i < nargs; ++i) {

+ 11 - 3
makepanda/makepanda.py

@@ -944,11 +944,12 @@ if (COMPILER=="GCC"):
     for pkg in MAYAVERSIONS:
         if (PkgSkip(pkg)==0 and (pkg in SDK)):
             if GetTarget() == 'darwin':
-                LibName(pkg, "-Wl,-rpath," + SDK[pkg] + "/Maya.app/Contents/MacOS")
+                LibName(pkg, "-Wl,-rpath,/Applications/Autodesk/" + pkg.lower() + "/Maya.app/Contents/MacOS")
             else:
                 LibName(pkg, "-Wl,-rpath," + SDK[pkg] + "/lib")
             LibName(pkg, "-lOpenMaya")
             LibName(pkg, "-lOpenMayaAnim")
+            LibName(pkg, "-lOpenMayaUI")
             LibName(pkg, "-lAnimSlice")
             LibName(pkg, "-lDeformSlice")
             LibName(pkg, "-lModifiers")
@@ -967,7 +968,8 @@ if (COMPILER=="GCC"):
             LibName(pkg, "-lDependEngine")
             LibName(pkg, "-lCommandEngine")
             LibName(pkg, "-lFoundation")
-            LibName(pkg, "-lIMFbase")
+            if pkg != "MAYA2020":
+                LibName(pkg, "-lIMFbase")
             if GetTarget() != 'darwin':
                 LibName(pkg, "-lOpenMayalib")
             else:
@@ -2612,7 +2614,13 @@ if not PkgSkip("PYTHON"):
     ConditionalWriteFile(GetOutputDir() + '/panda3d/__init__.py', p3d_init)
 
     # Also add this file, for backward compatibility.
-    ConditionalWriteFile(GetOutputDir() + '/panda3d/dtoolconfig.py', """
+    ConditionalWriteFile(GetOutputDir() + '/panda3d/dtoolconfig.py', """\
+'''Alias of :mod:`panda3d.interrogatedb`.
+
+.. deprecated:: 1.10.0
+   This module has been renamed to :mod:`panda3d.interrogatedb`.
+'''
+
 if __debug__:
     print("Warning: panda3d.dtoolconfig is deprecated, use panda3d.interrogatedb instead.")
 from .interrogatedb import *

+ 2 - 1
makepanda/makepandacore.py

@@ -106,6 +106,7 @@ MAYAVERSIONINFO = [("MAYA6",   "6.0"),
                    ("MAYA2017","2017"),
                    ("MAYA2018","2018"),
                    ("MAYA2019","2019"),
+                   ("MAYA2020","2020"),
 ]
 
 MAXVERSIONINFO = [("MAX6", "SOFTWARE\\Autodesk\\3DSMAX\\6.0", "installdir", "maxsdk\\cssdk\\include"),
@@ -2803,7 +2804,7 @@ def SetupVisualStudioEnviron():
         elif not win_kit.endswith('\\'):
             win_kit += '\\'
 
-        for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763:
+        for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763, 18362:
             version = "10.0.{0}.0".format(vnum)
             if os.path.isfile(win_kit + "Include\\" + version + "\\ucrt\\assert.h"):
                 print("Using Universal CRT %s" % (version))

+ 5 - 0
makepanda/makewheel.py

@@ -701,10 +701,15 @@ if __debug__:
             # Put the .exe files inside the panda3d-tools directory.
             whl.write_file('panda3d_tools/' + file, source_path)
 
+            if basename.endswith('_bin'):
+                # These tools won't be invoked by the user directly.
+                continue
+
             # Tell pip to create a wrapper script.
             funcname = basename.replace('-', '_')
             entry_points += '{0} = panda3d_tools:{1}\n'.format(basename, funcname)
             tools_init += '{0} = lambda: _exec_tool({1!r})\n'.format(funcname, file)
+
     entry_points += '[distutils.commands]\n'
     entry_points += 'build_apps = direct.dist.commands:build_apps\n'
     entry_points += 'bdist_apps = direct.dist.commands:bdist_apps\n'

+ 42 - 1
panda/src/cocoadisplay/cocoaGraphicsWindow.mm

@@ -45,6 +45,10 @@
 
 TypeHandle CocoaGraphicsWindow::_type_handle;
 
+#ifndef MAC_OS_X_VERSION_10_15
+#define NSAppKitVersionNumber10_14 1671
+#endif
+
 /**
  *
  */
@@ -1095,7 +1099,28 @@ set_properties_now(WindowProperties &properties) {
  */
 CGDisplayModeRef CocoaGraphicsWindow::
 find_display_mode(int width, int height) {
-  CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, NULL);
+  CFDictionaryRef options = NULL;
+  // On macOS 10.15+ (Catalina), we want to select the display mode with the
+  // samescaling factor as the current view to avoid cropping or scaling issues.
+  // This is a workaround until HiDPI display or scaling factor is properly
+  // handled. CGDisplayCopyAllDisplayModes() does not return upscaled display
+  // mode unless explicitly asked with kCGDisplayShowDuplicateLowResolutionModes
+  // (which is undocumented...).
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+  if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_14) {
+    const CFStringRef dictkeys[] = {kCGDisplayShowDuplicateLowResolutionModes};
+    const CFBooleanRef dictvalues[] = {kCFBooleanTrue};
+    options = CFDictionaryCreate(NULL,
+                                 (const void **)dictkeys,
+                                 (const void **)dictvalues,
+                                 1,
+                                 &kCFCopyStringDictionaryKeyCallBacks,
+                                 &kCFTypeDictionaryValueCallBacks);
+  }
+#endif
+  CFArrayRef modes = CGDisplayCopyAllDisplayModes(_display, options);
+  CFRelease(options);
+
   size_t num_modes = CFArrayGetCount(modes);
   CGDisplayModeRef mode;
 
@@ -1104,14 +1129,22 @@ find_display_mode(int width, int height) {
   int refresh_rate;
   mode = CGDisplayCopyDisplayMode(_display);
 
+#if __MAC_OS_X_VERSION_MAX_ALLOWED < 1080
   // First check if the current mode is adequate.
   if (CGDisplayModeGetWidth(mode) == width &&
       CGDisplayModeGetHeight(mode) == height) {
     return mode;
   }
+#endif
 
   current_pixel_encoding = CGDisplayModeCopyPixelEncoding(mode);
   refresh_rate = CGDisplayModeGetRefreshRate(mode);
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+  // Calculate the pixel width and height of the fullscreen mode we want using
+  // the currentdisplay mode dimensions and pixel dimensions.
+  size_t expected_pixel_width = (size_t(width) * CGDisplayModeGetPixelWidth(mode)) / CGDisplayModeGetWidth(mode);
+  size_t expected_pixel_height = (size_t(height) * CGDisplayModeGetPixelHeight(mode)) / CGDisplayModeGetHeight(mode);
+#endif
   CGDisplayModeRelease(mode);
 
   for (size_t i = 0; i < num_modes; ++i) {
@@ -1119,9 +1152,17 @@ find_display_mode(int width, int height) {
 
     CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(mode);
 
+    // As explained above, we want to select the fullscreen display mode using
+    // the same scaling factor, but only for MacOS 10.15+ To do this we check
+    // the mode width and heightbut also actual pixel widh and height.
     if (CGDisplayModeGetWidth(mode) == width &&
         CGDisplayModeGetHeight(mode) == height &&
         CGDisplayModeGetRefreshRate(mode) == refresh_rate &&
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+        (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_14 ||
+        (CGDisplayModeGetPixelWidth(mode) == expected_pixel_width &&
+         CGDisplayModeGetPixelHeight(mode) == expected_pixel_height)) &&
+#endif
         CFStringCompare(pixel_encoding, current_pixel_encoding, 0) == kCFCompareEqualTo) {
 
       CFRetain(mode);

+ 39 - 6
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -496,6 +496,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
     }
     #endif
 
+    dvbc->update_data_size_bytes(num_bytes);
     return dvbc;
   } else {
     dxgsg9_cat.error()
@@ -533,14 +534,42 @@ apply_vertex_buffer(VertexBufferContext *vbc,
         return false;
       }
 
-      PStatTimer timer(_load_vertex_buffer_pcollector, reader->get_current_thread());
 
-      #if 0
       if (dvbc->changed_size(reader)) {
-        // We have to destroy the old vertex buffer and create a new one.
-        dvbc->create_vbuffer(*_screen, reader);
+        // Destroy and recreate the buffer.
+        if (dvbc->_vbuffer != nullptr) {
+          dvbc->_vbuffer->Release();
+          dvbc->_vbuffer = nullptr;
+        }
+
+        DWORD usage;
+        D3DPOOL pool;
+        if (_screen->_managed_vertex_buffers) {
+          pool = D3DPOOL_MANAGED;
+          usage = D3DUSAGE_WRITEONLY;
+        } else {
+          pool = D3DPOOL_DEFAULT;
+          usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
+        }
+
+        PStatTimer timer(_create_vertex_buffer_pcollector, Thread::get_current_thread());
+
+        HRESULT hr;
+        int attempts = 0;
+        do {
+          hr = _screen->_d3d_device->CreateVertexBuffer(num_bytes, usage, dvbc->_fvf, pool, &dvbc->_vbuffer, nullptr);
+          attempts++;
+        } while (check_dx_allocation(hr, num_bytes, attempts));
+
+        if (FAILED(hr)) {
+          dvbc->_vbuffer = nullptr;
+          dxgsg9_cat.error()
+            << "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
+          return false;
+        }
       }
-      #endif
+
+      PStatTimer timer(_load_vertex_buffer_pcollector, reader->get_current_thread());
 
       HRESULT hr;
       BYTE *local_pointer;
@@ -5240,6 +5269,7 @@ calc_fb_properties(DWORD cformat, DWORD dformat,
 #define GAMMA_1 (255.0 * 256.0)
 
 static bool _gamma_table_initialized = false;
+static bool _gamma_changed = false;
 static unsigned short _original_gamma_table [256 * 3];
 
 void _create_gamma_table_dx9 (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
@@ -5337,6 +5367,7 @@ static_set_gamma(bool restore, PN_stdfloat gamma) {
 
     if (SetDeviceGammaRamp (hdc, ramp)) {
       set = true;
+      _gamma_changed = !restore;
     }
 
     ReleaseDC (nullptr, hdc);
@@ -5374,7 +5405,9 @@ restore_gamma() {
 void DXGraphicsStateGuardian9::
 atexit_function(void) {
   set_cg_device(nullptr);
-  static_set_gamma(true, 1.0f);
+  if (_gamma_changed) {
+    static_set_gamma(true, 1.0f);
+  }
 }
 
 /**

+ 22 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -2523,6 +2523,20 @@ reset() {
   }
 #endif
 
+#if defined(OPENGLES) && !defined(OPENGLES_1)
+  if (is_at_least_gles_version(3, 0)) {
+    _glReadBuffer = (PFNGLREADBUFFERPROC)
+      get_extension_func("glReadBuffer");
+
+  } else if (has_extension("GL_NV_read_buffer")) {
+    _glReadBuffer = (PFNGLREADBUFFERPROC)
+      get_extension_func("glReadBufferNV");
+
+  } else {
+    _glReadBuffer = nullptr;
+  }
+#endif
+
 #ifndef OPENGLES_1
   _max_color_targets = 1;
   if (_glDrawBuffers != nullptr) {
@@ -9060,7 +9074,7 @@ set_draw_buffer(int rbtype) {
  */
 void CLP(GraphicsStateGuardian)::
 set_read_buffer(int rbtype) {
-#ifndef OPENGLES  // Draw buffers not supported by OpenGL ES. (TODO!)
+#ifndef OPENGLES_1  // Draw buffers not supported by OpenGL ES 1.
   if (rbtype & (RenderBuffer::T_depth | RenderBuffer::T_stencil)) {
     // Special case: don't have to call ReadBuffer for these.
     return;
@@ -9093,10 +9107,14 @@ set_read_buffer(int rbtype) {
       }
       ++index;
     }
+#ifdef OPENGLES
+    _glReadBuffer(buffer);
+#else
     glReadBuffer(buffer);
+#endif
 
   } else {
-
+#ifndef OPENGLES
     switch (rbtype & RenderBuffer::T_color) {
     case RenderBuffer::T_front:
       glReadBuffer(GL_FRONT);
@@ -9133,10 +9151,11 @@ set_read_buffer(int rbtype) {
     default:
       break;
     }
+#endif  // OPENGLES
   }
 
   report_my_gl_errors();
-#endif  // OPENGLES
+#endif  // OPENGLES_1
 }
 
 /**

+ 5 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -92,6 +92,7 @@ typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
 typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
 typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
 typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
 typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
 typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
 typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
@@ -939,6 +940,10 @@ public:
   PFNGLBLITFRAMEBUFFEREXTPROC _glBlitFramebuffer;
   PFNGLDRAWBUFFERSPROC _glDrawBuffers;
 
+#if defined(OPENGLES) && !defined(OPENGLES_1)
+  PFNGLREADBUFFERPROC _glReadBuffer;
+#endif
+
 #ifndef OPENGLES_1
   PFNGLCLEARBUFFERFVPROC _glClearBufferfv;
   PFNGLCLEARBUFFERIVPROC _glClearBufferiv;

+ 4 - 4
panda/src/x11display/x11GraphicsPipe.cxx

@@ -371,13 +371,13 @@ find_fullscreen_crtc(const LPoint2i &point,
     for (int i = 0; i < res->ncrtc; ++i) {
       RRCrtc crtc = res->crtcs[i];
       if (auto info = get_crtc_info(res.get(), crtc)) {
-        if (point[0] >= info->x && point[0] < info->x + info->width &&
-            point[1] >= info->y && point[1] < info->y + info->height) {
+        if (point[0] >= info->x && point[0] < info->x + (int)info->width &&
+            point[1] >= info->y && point[1] < info->y + (int)info->height) {
 
           x = info->x;
           y = info->y;
-          width = info->width;
-          height = info->height;
+          width = (int)info->width;
+          height = (int)info->height;
           return crtc;
         }
       }

+ 15 - 18
pandatool/src/mayaprogs/mayapath.cxx

@@ -107,6 +107,7 @@ struct MayaVerInfo maya_versions[] = {
   { "MAYA2017", "2017"},
   { "MAYA2018", "2018"},
   { "MAYA2019", "2019"},
+  { "MAYA2020", "2020"},
   { 0, 0 },
 };
 
@@ -194,26 +195,22 @@ int
 main(int argc, char *argv[]) {
   // First, get the command line and append _bin, so we will actually run
   // maya2egg_bin.exe, egg2maya_bin.exe, etc.
-  Filename command = Filename::from_os_specific(argv[0]);
-  if (!command.is_fully_qualified()) {
-    DSearchPath path;
-    path.append_path(ExecutionEnvironment::get_environment_variable("PATH"));
-#ifdef _WIN32
-    command.set_extension("exe");
-#endif
-    command.resolve_filename(path);
-  }
-
-#ifdef _WIN32
-  if (command.get_extension() == "exe") {
-    command.set_extension("");
+  Filename command = ExecutionEnvironment::get_binary_name();
+
+  if (command.empty() || command == "unknown" || !command.exists()) {
+    command = Filename::from_os_specific(argv[0]);
+
+    if (!command.is_fully_qualified()) {
+      DSearchPath path;
+      path.append_path(ExecutionEnvironment::get_environment_variable("PATH"));
+  #ifdef _WIN32
+      command.set_extension("exe");
+  #endif
+      command.resolve_filename(path);
+    }
   }
-#endif
 
-  command = command.get_fullpath() + string("_bin");
-#ifdef _WIN32
-  command.set_extension("exe");
-#endif
+  command.set_basename_wo_extension(command.get_basename_wo_extension() + "_bin");
   string os_command = command.to_os_specific();
 
   // First start with $PANDA_MAYA_LOCATION.  If it is set, it overrides

+ 36 - 0
tests/dcparser/test_dcpacker.py

@@ -0,0 +1,36 @@
+import pytest
+
+direct = pytest.importorskip("panda3d.direct")
+
+
+def test_pack_int8():
+    for num in range(-128, 128):
+        packer = direct.DCPacker()
+        packer.raw_pack_int8(num)
+        packer.set_unpack_data(packer.get_bytes())
+        assert packer.raw_unpack_int8() == num
+
+
+def test_pack_uint8():
+    for num in range(256):
+        packer = direct.DCPacker()
+        packer.raw_pack_uint8(num)
+        packer.set_unpack_data(packer.get_bytes())
+        assert packer.raw_unpack_uint8() == num
+
+
+def test_pack_int64():
+    for num in (0, -1, 0x7fffffff, -0x80000000, 0x7fffffffffffffff, 0x7ffffffffffffffe, -0x8000000000000000, -0x7fffffffffffffff):
+        packer = direct.DCPacker()
+        packer.raw_pack_int64(num)
+        packer.set_unpack_data(packer.get_bytes())
+        assert packer.raw_unpack_int64() == num
+
+
+def test_pack_uint64():
+    for num in (0, 1, 0x7fffffff, 0xffffffff, 0x7fffffffffffffff, 0xfffffffffffffffe, 0xffffffffffffffff):
+        packer = direct.DCPacker()
+        packer.raw_pack_uint64(num)
+        packer.set_unpack_data(packer.get_bytes())
+        assert packer.raw_unpack_uint64() == num
+