ソースを参照

Merge branch 'master' into shaderpipeline

rdb 5 年 前
コミット
9b01e4b052
51 ファイル変更891 行追加587 行削除
  1. 1 1
      .editorconfig
  2. 1 1
      .github/codecov.yml
  3. 2 0
      direct/src/dcparser/dcClass.cxx
  4. 3 2
      direct/src/dcparser/dcClass.h
  5. 3 0
      direct/src/dcparser/dcLexer.cxx.prebuilt
  6. 3 1
      direct/src/dcparser/dcLexer.lxx
  7. 2 0
      direct/src/dcparser/dcbase.h
  8. 0 5
      direct/src/dist/commands.py
  9. 0 1
      direct/src/showbase/ProfileSession.py
  10. 1 1
      dtool/Package.cmake
  11. 432 353
      dtool/src/cppparser/cppBison.cxx.prebuilt
  12. 6 2
      dtool/src/cppparser/cppBison.h.prebuilt
  13. 13 37
      dtool/src/cppparser/cppBison.yxx
  14. 47 9
      dtool/src/cppparser/cppExpression.cxx
  15. 3 1
      dtool/src/cppparser/cppExpression.h
  16. 11 1
      dtool/src/cppparser/cppInstance.cxx
  17. 1 1
      dtool/src/cppparser/cppInstanceIdentifier.cxx
  18. 2 2
      dtool/src/cppparser/cppInstanceIdentifier.h
  19. 15 11
      dtool/src/parser-inc/map
  20. 2 0
      dtool/src/parser-inc/ostream
  21. 9 8
      dtool/src/parser-inc/string
  22. 10 6
      dtool/src/parser-inc/vector
  23. 28 4
      makepanda/makepanda.py
  24. 16 3
      panda/metalibs/pandagl/pandagl.cxx
  25. 2 1
      panda/src/collide/collisionPolygon.h
  26. 1 1
      panda/src/display/frameBufferProperties.cxx
  27. 3 3
      panda/src/downloader/httpClient.I
  28. 7 3
      panda/src/egldisplay/config_egldisplay.cxx
  29. 6 4
      panda/src/egldisplay/config_egldisplay.h
  30. 5 3
      panda/src/egldisplay/eglGraphicsBuffer.cxx
  31. 8 0
      panda/src/egldisplay/eglGraphicsPipe.I
  32. 44 3
      panda/src/egldisplay/eglGraphicsPipe.cxx
  33. 20 10
      panda/src/egldisplay/eglGraphicsPipe.h
  34. 9 4
      panda/src/egldisplay/eglGraphicsPixmap.cxx
  35. 4 0
      panda/src/egldisplay/eglGraphicsPixmap.h
  36. 63 62
      panda/src/egldisplay/eglGraphicsStateGuardian.cxx
  37. 19 20
      panda/src/egldisplay/eglGraphicsStateGuardian.h
  38. 8 3
      panda/src/egldisplay/eglGraphicsWindow.cxx
  39. 4 0
      panda/src/egldisplay/eglGraphicsWindow.h
  40. 8 0
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  41. 1 0
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  42. 4 4
      panda/src/grutil/meshDrawer2D.I
  43. 2 2
      panda/src/grutil/meshDrawer2D.h
  44. 12 4
      panda/src/nativenet/buffered_datagramconnection.h
  45. 7 5
      panda/src/pgraph/geomNode.cxx
  46. 6 0
      panda/src/pgraph/pandaNode_ext.cxx
  47. 3 0
      pandatool/src/deploy-stub/deploy-stub.c
  48. 0 1
      samples/fireflies/light.sha
  49. 29 0
      tests/pgraph/test_nodepath.py
  50. 3 2
      tests/putil/test_bitarray.py
  51. 2 2
      tests/putil/test_clockobject.py

+ 1 - 1
.editorconfig

@@ -10,7 +10,7 @@ insert_final_newline = true
 indent_style = space
 indent_size = 4
 
-[*.{h,c,cxx,cpp,I}]
+[*.{h,c,cxx,cpp,I,T}]
 indent_style = space
 indent_size = 2
 

+ 1 - 1
.github/codecov.yml

@@ -5,7 +5,7 @@ coverage:
         threshold: 0.1
     patch:
       default:
-        threshold: 0.1
+        target: 0%
 codecov:
   require_ci_to_pass: true
   notify:

+ 2 - 0
direct/src/dcparser/dcClass.cxx

@@ -77,7 +77,9 @@ DCClass(DCFile *dc_file, const string &name, bool is_struct, bool bogus_class) :
   _number = -1;
   _constructor = nullptr;
 
+#ifdef WITHIN_PANDA
   _python_class_defs = nullptr;
+#endif
 }
 
 /**

+ 3 - 2
direct/src/dcparser/dcClass.h

@@ -172,6 +172,9 @@ private:
   typedef pmap<int, DCField *> FieldsByIndex;
   FieldsByIndex _fields_by_index;
 
+  friend class DCField;
+
+#ifdef WITHIN_PANDA
   // See pandaNode.h for an explanation of this trick
   class PythonClassDefs : public ReferenceCount {
   public:
@@ -179,8 +182,6 @@ private:
   };
   PT(PythonClassDefs) _python_class_defs;
 
-  friend class DCField;
-#ifdef WITHIN_PANDA
   friend class Extension<DCClass>;
 #endif
 };

+ 3 - 0
direct/src/dcparser/dcLexer.cxx.prebuilt

@@ -599,7 +599,10 @@ char *dcyytext;
 #include "dcParser.h"
 #include "dcFile.h"
 #include "dcindent.h"
+
+#ifdef WITHIN_PANDA
 #include "pstrtod.h"
+#endif
 
 
 static int yyinput(void);        // declared by flex.

+ 3 - 1
direct/src/dcparser/dcLexer.lxx

@@ -11,8 +11,10 @@
 #include "dcParser.h"
 #include "dcFile.h"
 #include "dcindent.h"
-#include "pstrtod.h"
 
+#ifdef WITHIN_PANDA
+#include "pstrtod.h"
+#endif
 
 static int yyinput(void);        // declared by flex.
 extern "C" int dcyywrap();

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

@@ -70,6 +70,7 @@
 #define BEGIN_PUBLISH
 #define END_PUBLISH
 #define BLOCKING
+#define EXTENSION(x)
 
 // These control the declspec(dllexport/dllimport) on Windows.  When compiling
 // outside of Panda, we assume we aren't part of a DLL.
@@ -100,6 +101,7 @@ typedef std::string Filename;
 #define pmap std::map
 #define pset std::set
 #define vector_uchar std::vector<unsigned char>
+#define patof(x) atof(x)
 
 #include <stdint.h>
 #include <string.h>

+ 0 - 5
direct/src/dist/commands.py

@@ -4,8 +4,6 @@ See the :ref:`distribution` section of the programming manual for information
 on how to use these commands.
 """
 
-from __future__ import print_function
-
 import collections
 import os
 import plistlib
@@ -31,9 +29,6 @@ import panda3d.core as p3d
 
 
 if sys.version_info < (3, 0):
-    # Python 3 defines these subtypes of IOError, but Python 2 doesn't.
-    FileNotFoundError = IOError
-
     # Warn the user.  They might be using Python 2 by accident.
     print("=================================================================")
     print("WARNING: You are using Python 2, which has reached the end of its")

+ 0 - 1
direct/src/showbase/ProfileSession.py

@@ -1,4 +1,3 @@
-from __future__ import print_function
 from panda3d.core import TrueClock
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.showbase.PythonUtil import (

+ 1 - 1
dtool/Package.cmake

@@ -390,7 +390,7 @@ package_status(SQUISH "libsquish")
 #
 
 # Assimp
-find_package(Assimp QUIET)
+find_package(Assimp QUIET MODULE)
 
 package_option(Assimp
   "Build pandatool with support for loading 3D assets supported by Assimp.")

ファイルの差分が大きいため隠しています
+ 432 - 353
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 6 - 2
dtool/src/cppparser/cppBison.h.prebuilt

@@ -1,8 +1,9 @@
-/* A Bison parser, made by GNU Bison 3.0.5.  */
+/* A Bison parser, made by GNU Bison 3.5.3.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
+   Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,9 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+/* Undocumented macros, especially those whose name start with YY_,
+   are private implementation details.  Do not rely on them.  */
+
 #ifndef YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
 # define YY_CPPYY_BUILT_TMP_CPPBISON_YXX_H_INCLUDED
 /* Debug traces.  */

+ 13 - 37
dtool/src/cppparser/cppBison.yxx

@@ -1891,7 +1891,7 @@ instance_identifier_and_maybe_trailing_return_type:
   }
   $$ = $1;
 }
-        | instance_identifier ':' INTEGER
+        | instance_identifier ':' const_expr
 {
   // Bitfield definition.
   $1->_bit_width = $3;
@@ -3278,17 +3278,9 @@ no_angle_bracket_const_expr:
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
 }
-        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+        | KW_SIZEOF no_angle_bracket_const_expr %prec UNARY
 {
-  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
-  if (arg == nullptr) {
-    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
-  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
-    CPPInstance *inst = arg->as_instance();
-    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
-  } else {
-    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
-  }
+  $$ = new CPPExpression(CPPExpression::sizeof_func($2));
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
@@ -3402,9 +3394,9 @@ no_angle_bracket_const_expr:
 {
   $$ = new CPPExpression('f', $1);
 }
-        | no_angle_bracket_const_expr '.' no_angle_bracket_const_expr
+        | no_angle_bracket_const_expr '.' name
 {
-  $$ = new CPPExpression('.', $1, $3);
+  $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer));
 }
         | no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr
 {
@@ -3542,17 +3534,9 @@ const_expr:
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
 }
-        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+        | KW_SIZEOF const_expr %prec UNARY
 {
-  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
-  if (arg == nullptr) {
-    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
-  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
-    CPPInstance *inst = arg->as_instance();
-    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
-  } else {
-    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
-  }
+  $$ = new CPPExpression(CPPExpression::sizeof_func($2));
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
@@ -3704,9 +3688,9 @@ const_expr:
 {
   $$ = new CPPExpression('f', $1);
 }
-        | const_expr '.' const_expr
+        | const_expr '.' name
 {
-  $$ = new CPPExpression('.', $1, $3);
+  $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer));
 }
         | const_expr POINTSAT const_expr
 {
@@ -3886,17 +3870,9 @@ formal_const_expr:
 {
   $$ = new CPPExpression(CPPExpression::sizeof_func($3));
 }
-        | KW_SIZEOF '(' IDENTIFIER ')' %prec UNARY
+        | KW_SIZEOF formal_const_expr %prec UNARY
 {
-  CPPDeclaration *arg = $3->find_symbol(current_scope, global_scope, current_lexer);
-  if (arg == nullptr) {
-    yyerror("undefined sizeof argument: " + $3->get_fully_scoped_name(), @3);
-  } else if (arg->get_subtype() == CPPDeclaration::ST_instance) {
-    CPPInstance *inst = arg->as_instance();
-    $$ = new CPPExpression(CPPExpression::sizeof_func(inst->_type));
-  } else {
-    $$ = new CPPExpression(CPPExpression::sizeof_func(arg->as_type()));
-  }
+  $$ = new CPPExpression(CPPExpression::sizeof_func($2));
 }
         | KW_SIZEOF ELLIPSIS '(' name ')' %prec UNARY
 {
@@ -4044,9 +4020,9 @@ formal_const_expr:
 {
   $$ = new CPPExpression('f', $1);
 }
-        | formal_const_expr '.' const_expr
+        | formal_const_expr '.' name
 {
-  $$ = new CPPExpression('.', $1, $3);
+  $$ = new CPPExpression('.', $1, new CPPExpression($3, current_scope, global_scope, current_lexer));
 }
         | formal_const_expr POINTSAT const_expr
 {

+ 47 - 9
dtool/src/cppparser/cppExpression.cxx

@@ -429,12 +429,24 @@ type_trait(int trait, CPPType *type, CPPType *arg) {
 CPPExpression CPPExpression::
 sizeof_func(CPPType *type) {
   CPPExpression expr(0);
-  expr._type = T_sizeof;
+  expr._type = T_sizeof_type;
   expr._u._typecast._to = type;
   expr._u._typecast._op1 = nullptr;
   return expr;
 }
 
+/**
+ *
+ */
+CPPExpression CPPExpression::
+sizeof_func(CPPExpression *op1) {
+  CPPExpression expr(0);
+  expr._type = T_sizeof_expr;
+  expr._u._typecast._to = nullptr;
+  expr._u._typecast._op1 = op1;
+  return expr;
+}
+
 /**
  *
  */
@@ -629,7 +641,8 @@ evaluate() const {
   case T_empty_aggregate_init:
   case T_new:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
+  case T_sizeof_expr:
   case T_sizeof_ellipsis:
     return Result();
 
@@ -1058,7 +1071,8 @@ determine_type() const {
   case T_default_new:
     return CPPType::new_type(new CPPPointerType(_u._typecast._to));
 
-  case T_sizeof:
+  case T_sizeof_type:
+  case T_sizeof_expr:
   case T_sizeof_ellipsis:
   case T_alignof:
     // Note: this should actually be size_t, but that is defined as a typedef
@@ -1334,10 +1348,13 @@ is_fully_specified() const {
   case T_default_construct:
   case T_empty_aggregate_init:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
     return _u._typecast._to->is_fully_specified();
 
+  case T_sizeof_expr:
+    return _u._typecast._op1->is_fully_specified();
+
   case T_sizeof_ellipsis:
     return _u._ident->is_fully_specified();
 
@@ -1469,7 +1486,7 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   case T_default_construct:
   case T_empty_aggregate_init:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
     rep->_u._typecast._to =
       _u._typecast._to->substitute_decl(subst, current_scope, global_scope)
@@ -1477,6 +1494,13 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
     any_changed = any_changed || (rep->_u._typecast._to != _u._typecast._to);
     break;
 
+  case T_sizeof_expr:
+    rep->_u._typecast._op1 =
+      _u._typecast._op1->substitute_decl(subst, current_scope, global_scope)
+      ->as_expression();
+    any_changed = any_changed || (rep->_u._typecast._op1 != _u._typecast._op1);
+    break;
+
   case T_trinary_operation:
     rep->_u._op._op3 =
       _u._op._op3->substitute_decl(subst, current_scope, global_scope)
@@ -1567,10 +1591,13 @@ is_tbd() const {
   case T_new:
   case T_default_construct:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
     return _u._typecast._to->is_tbd();
 
+  case T_sizeof_expr:
+    return _u._typecast._op1->is_tbd();
+
   case T_trinary_operation:
     if (_u._op._op3->is_tbd()) {
       return true;
@@ -1807,12 +1834,17 @@ output(std::ostream &out, int indent_level, CPPScope *scope, bool) const {
     out << "())";
     break;
 
-  case T_sizeof:
+  case T_sizeof_type:
     out << "sizeof(";
     _u._typecast._to->output(out, indent_level, scope, false);
     out << ")";
     break;
 
+  case T_sizeof_expr:
+    out << "sizeof ";
+    _u._typecast._op1->output(out, indent_level, scope, false);
+    break;
+
   case T_sizeof_ellipsis:
     out << "sizeof...(";
     _u._ident->output(out, scope);
@@ -2222,10 +2254,13 @@ is_equal(const CPPDeclaration *other) const {
   case T_default_construct:
   case T_empty_aggregate_init:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
     return _u._typecast._to == ot->_u._typecast._to;
 
+  case T_sizeof_expr:
+    return _u._typecast._op1 == ot->_u._typecast._op1;
+
   case T_unary_operation:
     return *_u._op._op1 == *ot->_u._op._op1;
 
@@ -2324,10 +2359,13 @@ is_less(const CPPDeclaration *other) const {
   case T_default_construct:
   case T_empty_aggregate_init:
   case T_default_new:
-  case T_sizeof:
+  case T_sizeof_type:
   case T_alignof:
     return _u._typecast._to < ot->_u._typecast._to;
 
+  case T_sizeof_expr:
+    return _u._typecast._op1 < ot->_u._typecast._op1;
+
   case T_trinary_operation:
     if (*_u._op._op3 != *ot->_u._op._op3) {
       return *_u._op._op3 < *ot->_u._op._op3;

+ 3 - 1
dtool/src/cppparser/cppExpression.h

@@ -52,7 +52,8 @@ public:
     T_empty_aggregate_init,
     T_new,
     T_default_new,
-    T_sizeof,
+    T_sizeof_type,
+    T_sizeof_expr,
     T_sizeof_ellipsis,
     T_alignof,
     T_unary_operation,
@@ -89,6 +90,7 @@ public:
   static CPPExpression typeid_op(CPPExpression *op1, CPPType *std_type_info);
   static CPPExpression type_trait(int trait, CPPType *type, CPPType *arg = nullptr);
   static CPPExpression sizeof_func(CPPType *type);
+  static CPPExpression sizeof_func(CPPExpression *op1);
   static CPPExpression sizeof_ellipsis_func(CPPIdentifier *ident);
   static CPPExpression alignof_func(CPPType *type);
   static CPPExpression lambda(CPPClosureType *type);

+ 11 - 1
dtool/src/cppparser/cppInstance.cxx

@@ -74,7 +74,17 @@ CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
   ii->_ident = nullptr;
   _storage_class = storage_class;
   _initializer = nullptr;
-  _bit_width = ii->_bit_width;
+
+  if (ii->_bit_width != nullptr) {
+    CPPExpression::Result result = ii->_bit_width->evaluate();
+    if (result._type != CPPExpression::RT_error) {
+      _bit_width = ii->_bit_width->evaluate().as_integer();
+    } else {
+      _bit_width = -1;
+    }
+  } else {
+    _bit_width = -1;
+  }
 
   CPPParameterList *params = ii->get_initializer();
   if (params != nullptr) {

+ 1 - 1
dtool/src/cppparser/cppInstanceIdentifier.cxx

@@ -82,7 +82,7 @@ initializer_type(CPPParameterList *params) {
 CPPInstanceIdentifier::
 CPPInstanceIdentifier(CPPIdentifier *ident) :
   _ident(ident),
-  _bit_width(-1),
+  _bit_width(nullptr),
   _packed(false) {
 }
 

+ 2 - 2
dtool/src/cppparser/cppInstanceIdentifier.h

@@ -86,8 +86,8 @@ public:
   typedef std::vector<Modifier> Modifiers;
   Modifiers _modifiers;
 
-  // If not -1, indicates a bitfield
-  int _bit_width;
+  // If not null, indicates a bitfield
+  CPPExpression *_bit_width;
 
   // Indicates a parameter pack
   bool _packed;

+ 15 - 11
dtool/src/parser-inc/map

@@ -24,19 +24,23 @@
 #include <stdcompare.h>
 #include <pair>
 
-template<class key, class element, class compare = less<key> >
+namespace std {
+  template<class T> class allocator;
+}
+
+template<class Key, class Element, class Compare = less<Key>, class Allocator = std::allocator<pair<const Key, T> > >
 class map {
 public:
-  typedef key key_type;
-  typedef element data_type;
-  typedef element mapped_type;
-  typedef pair<const key, element> value_type;
-  typedef compare key_compare;
-
-  typedef element *pointer;
-  typedef const element *const_pointer;
-  typedef element &reference;
-  typedef const element &const_reference;
+  typedef Key key_type;
+  typedef Element data_type;
+  typedef Element mapped_type;
+  typedef pair<const Key, Element> value_type;
+  typedef Compare key_compare;
+
+  typedef Element *pointer;
+  typedef const Element *const_pointer;
+  typedef Element &reference;
+  typedef const Element &const_reference;
 
   class iterator;
   class const_iterator;

+ 2 - 0
dtool/src/parser-inc/ostream

@@ -1,5 +1,7 @@
 #pragma once
 
+#include <iosfwd>
+
 namespace std {
   template<class CharT, class Traits>
   std::basic_ostream<CharT, Traits> &ends(std::basic_ostream<CharT, Traits> &os);

+ 9 - 8
dtool/src/parser-inc/string

@@ -26,6 +26,7 @@
 
 namespace std {
   template<class charT> struct char_traits;
+  template<class T> class allocator;
 
   template<> struct char_traits<char> {
     using char_type = char;
@@ -51,7 +52,7 @@ namespace std {
     using state_type = mbstate_t;
   };
 
-  template<class ctype>
+  template<class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT> >
   class basic_string {
   public:
     struct iterator;
@@ -63,17 +64,17 @@ namespace std {
     static const size_t npos = -1;
 
     basic_string();
-    basic_string(const basic_string<ctype> &copy);
-    void operator = (const basic_string<ctype> &copy);
-    basic_string(const ctype *string);
+    basic_string(const basic_string<CharT> &copy);
+    void operator = (const basic_string<CharT> &copy);
+    basic_string(const CharT *string);
     ~basic_string();
 
-    const ctype *c_str() const;
+    const CharT *c_str() const;
     size_t length() const;
 
-    ctype at(size_t pos) const;
-    ctype operator[](size_t pos) const;
-    ctype &operator[](size_t pos);
+    CharT at(size_t pos) const;
+    CharT operator[](size_t pos) const;
+    CharT &operator[](size_t pos);
   };
 
   typedef basic_string<char> string;

+ 10 - 6
dtool/src/parser-inc/vector

@@ -22,17 +22,21 @@
 
 #include <stdtypedefs.h>
 
+namespace std {
+  template<class T> class allocator;
+}
+
 inline namespace std {
 
-template<class element>
+template<class T, class Allocator = std::allocator<T> >
 class vector {
 public:
-  typedef element value_type;
+  typedef T value_type;
 
-  typedef element *pointer;
-  typedef const element *const_pointer;
-  typedef element &reference;
-  typedef const element &const_reference;
+  typedef T *pointer;
+  typedef const T *const_pointer;
+  typedef T &reference;
+  typedef const T &const_reference;
 
   typedef pointer iterator;
   typedef const_pointer const_iterator;

+ 28 - 4
makepanda/makepanda.py

@@ -2390,6 +2390,9 @@ def WriteConfigSettings():
         if int(platform.mac_ver()[0][3]) <= 4:
             dtool_config["PHAVE_UCONTEXT_H"] = 'UNDEF'
 
+    if PkgSkip("X11"):
+        dtool_config["HAVE_GLX"] = 'UNDEF'
+
     if (GetTarget() == "freebsd"):
         dtool_config["IS_LINUX"] = 'UNDEF'
         dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF'
@@ -4546,13 +4549,33 @@ if (GetTarget() == 'windows' and PkgSkip("GL")==0):
 # DIRECTORY: panda/src/egldisplay/
 #
 
-if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0):
+# If we're not compiling with any windowing system at all, but we do have EGL,
+# we can use that to create a headless libpandagl instead.
+if not PkgSkip("EGL") and not PkgSkip("GL") and PkgSkip("X11") and GetTarget() not in ('windows', 'darwin'):
+  DefSymbol('EGL', 'HAVE_EGL', '')
+  OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGL', 'GL', 'EGL']
+  TargetAdd('pandagl_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx')
+  OPTS=['DIR:panda/metalibs/pandagl', 'BUILDING:PANDAGL', 'GL', 'EGL']
+  TargetAdd('pandagl_pandagl.obj', opts=OPTS, input='pandagl.cxx')
+  TargetAdd('libpandagl.dll', input='pandagl_pandagl.obj')
+  TargetAdd('libpandagl.dll', input='p3glgsg_config_glgsg.obj')
+  TargetAdd('libpandagl.dll', input='p3glgsg_glgsg.obj')
+  TargetAdd('libpandagl.dll', input='pandagl_egldisplay_composite1.obj')
+  TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
+  TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'EGL', 'CGGL'])
+
+#
+# DIRECTORY: panda/src/egldisplay/
+#
+
+if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0):
   DefSymbol('GLES', 'OPENGLES_1', '')
   OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES',  'GLES', 'EGL']
   TargetAdd('pandagles_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx')
   OPTS=['DIR:panda/metalibs/pandagles', 'BUILDING:PANDAGLES', 'GLES', 'EGL']
   TargetAdd('pandagles_pandagles.obj', opts=OPTS, input='pandagles.cxx')
-  TargetAdd('libpandagles.dll', input='p3x11display_composite1.obj')
+  if not PkgSkip("X11"):
+    TargetAdd('libpandagles.dll', input='p3x11display_composite1.obj')
   TargetAdd('libpandagles.dll', input='pandagles_pandagles.obj')
   TargetAdd('libpandagles.dll', input='p3glesgsg_config_glesgsg.obj')
   TargetAdd('libpandagles.dll', input='p3glesgsg_glesgsg.obj')
@@ -4564,13 +4587,14 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0):
 # DIRECTORY: panda/src/egldisplay/
 #
 
-if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0):
+if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0):
   DefSymbol('GLES2', 'OPENGLES_2', '')
   OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES2',  'GLES2', 'EGL']
   TargetAdd('pandagles2_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx')
   OPTS=['DIR:panda/metalibs/pandagles2', 'BUILDING:PANDAGLES2', 'GLES2', 'EGL']
   TargetAdd('pandagles2_pandagles2.obj', opts=OPTS, input='pandagles2.cxx')
-  TargetAdd('libpandagles2.dll', input='p3x11display_composite1.obj')
+  if not PkgSkip("X11"):
+    TargetAdd('libpandagles2.dll', input='p3x11display_composite1.obj')
   TargetAdd('libpandagles2.dll', input='pandagles2_pandagles2.obj')
   TargetAdd('libpandagles2.dll', input='p3gles2gsg_config_gles2gsg.obj')
   TargetAdd('libpandagles2.dll', input='p3gles2gsg_gles2gsg.obj')

+ 16 - 3
panda/metalibs/pandagl/pandagl.cxx

@@ -23,8 +23,13 @@
 #include "glxGraphicsPipe.h"
 #endif
 
-#if !defined(HAVE_WGL) && !defined(HAVE_COCOA) && !defined(HAVE_GLX)
-#error One of HAVE_WGL, HAVE_COCOA or HAVE_GLX must be defined when compiling pandagl!
+#if defined(HAVE_EGL) && !defined(HAVE_X11)
+#include "config_egldisplay.h"
+#include "eglGraphicsPipe.h"
+#endif
+
+#if !defined(HAVE_WGL) && !defined(HAVE_COCOA) && !defined(HAVE_GLX) && !defined(HAVE_EGL)
+#error One of HAVE_WGL, HAVE_COCOA, HAVE_GLX or HAVE_EGL must be defined when compiling pandagl!
 #endif
 
 /**
@@ -45,9 +50,13 @@ init_libpandagl() {
   init_libcocoadisplay();
 #endif
 
-#ifdef IS_LINUX
+#ifdef HAVE_GLX
   init_libglxdisplay();
 #endif
+
+#if defined(HAVE_EGL) && !defined(HAVE_X11)
+  init_libegldisplay();
+#endif
 }
 
 /**
@@ -68,5 +77,9 @@ get_pipe_type_pandagl() {
   return glxGraphicsPipe::get_class_type().get_index();
 #endif
 
+#if defined(HAVE_EGL) && !defined(HAVE_X11)
+  return eglGraphicsPipe::get_class_type().get_index();
+#endif
+
   return 0;
 }

+ 2 - 1
panda/src/collide/collisionPolygon.h

@@ -42,6 +42,8 @@ public:
 
   virtual CollisionSolid *make_copy();
 
+  static bool verify_points(const LPoint3 *begin, const LPoint3 *end);
+
 PUBLISHED:
   virtual LPoint3 get_collision_origin() const;
 
@@ -53,7 +55,6 @@ PUBLISHED:
   INLINE static bool verify_points(const LPoint3 &a, const LPoint3 &b,
                                    const LPoint3 &c, const LPoint3 &d);
   static bool verify_points(const LPoint3 &a, const LPoint3 &b, const LPoint3 &c);
-  static bool verify_points(const LPoint3 *begin, const LPoint3 *end);
 
   bool is_valid() const;
   bool is_concave() const;

+ 1 - 1
panda/src/display/frameBufferProperties.cxx

@@ -605,7 +605,7 @@ verify_hardware_software(const FrameBufferProperties &props, const std::string &
 
   if (get_force_hardware() < props.get_force_hardware()) {
     display_cat.error()
-      << "The application requested harware acceleration, but your OpenGL\n";
+      << "The application requested hardware acceleration, but your OpenGL\n";
     display_cat.error()
       << "driver, " << renderer << ", only supports software rendering.\n";
     display_cat.error()

+ 3 - 3
panda/src/downloader/httpClient.I

@@ -111,9 +111,9 @@ get_verify_ssl() const {
  * Specifies the set of ciphers that are to be made available for SSL
  * connections.  This is a string as described in the ciphers(1) man page of
  * the OpenSSL documentation (or see
- * https://www.openssl.org/docs/apps/ciphers.html ).  If this isn't specified,
- * the default is provided by the Config file.  You may also specify "DEFAULT"
- * to use the built-in OpenSSL default value.
+ * https://www.openssl.org/docs/man1.1.1/man1/ciphers.html ).  If this isn't
+ * specified, the default is provided by the Config file.  You may also specify
+ * "DEFAULT" to use the built-in OpenSSL default value.
  */
 INLINE void HTTPClient::
 set_cipher_list(const std::string &cipher_list) {

+ 7 - 3
panda/src/egldisplay/config_egldisplay.cxx

@@ -19,8 +19,8 @@
 #include "dconfig.h"
 #include "pandaSystem.h"
 
-#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_PANDAGLES) && !defined(BUILDING_PANDAGLES2)
-  #error Buildsystem error: BUILDING_PANDAGLES(2) not defined
+#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_PANDAGLES) && !defined(BUILDING_PANDAGLES2) && !defined(BUILDING_PANDAGL)
+  #error Buildsystem error: BUILDING_PANDAGL(ES(2)) not defined
 #endif
 
 Configure(config_egldisplay);
@@ -45,7 +45,9 @@ init_libegldisplay() {
   initialized = true;
 
   eglGraphicsPipe::init_type();
+#ifdef HAVE_X11
   eglGraphicsWindow::init_type();
+#endif
   eglGraphicsStateGuardian::init_type();
 
   GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
@@ -55,8 +57,10 @@ init_libegldisplay() {
   PandaSystem *ps = PandaSystem::get_global_ptr();
 #ifdef OPENGLES_2
   ps->set_system_tag("OpenGL ES 2", "window_system", "EGL");
-#else
+#elif defined(OPENGLES_1)
   ps->set_system_tag("OpenGL ES", "window_system", "EGL");
+#else
+  ps->set_system_tag("OpenGL", "window_system", "EGL");
 #endif
 }
 

+ 6 - 4
panda/src/egldisplay/config_egldisplay.h

@@ -23,20 +23,22 @@
 #if defined(OPENGLES_1) && defined(OPENGLES_2)
   #error OPENGLES_1 and OPENGLES_2 cannot be defined at the same time!
 #endif
-#if !defined(OPENGLES_1) && !defined(OPENGLES_2)
-  #error Either OPENGLES_1 or OPENGLES_2 must be defined when compiling egldisplay!
-#endif
 
 #ifdef OPENGLES_2
   NotifyCategoryDecl(egldisplay, EXPCL_PANDAGLES2, EXPTP_PANDAGLES2);
 
   extern EXPCL_PANDAGLES2 void init_libegldisplay();
   extern EXPCL_PANDAGLES2 const std::string get_egl_error_string(int error);
-#else
+#elif defined(OPENGLES_1)
   NotifyCategoryDecl(egldisplay, EXPCL_PANDAGLES, EXPTP_PANDAGLES);
 
   extern EXPCL_PANDAGLES void init_libegldisplay();
   extern EXPCL_PANDAGLES const std::string get_egl_error_string(int error);
+#else
+  NotifyCategoryDecl(egldisplay, EXPCL_PANDAGL, EXPTP_PANDAGL);
+
+  extern EXPCL_PANDAGL void init_libegldisplay();
+  extern EXPCL_PANDAGL const std::string get_egl_error_string(int error);
 #endif
 
 #endif

+ 5 - 3
panda/src/egldisplay/eglGraphicsBuffer.cxx

@@ -127,7 +127,7 @@ close_buffer() {
   if (_gsg != nullptr) {
     eglGraphicsStateGuardian *eglgsg;
     DCAST_INTO_V(eglgsg, _gsg);
-    if (!eglMakeCurrent(eglgsg->_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
+    if (!eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
       egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
         << get_egl_error_string(eglGetError()) << "\n";
     }
@@ -159,7 +159,7 @@ open_buffer() {
   if (_gsg == 0) {
     // There is no old gsg.  Create a new one.
     eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr);
-    eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false);
+    eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, true, false);
     _gsg = eglgsg;
   } else {
     // If the old gsg has the wrong pixel format, create a new one that shares
@@ -167,7 +167,7 @@ open_buffer() {
     DCAST_INTO_R(eglgsg, _gsg, false);
     if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
       eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
-      eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false);
+      eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, true, false);
       _gsg = eglgsg;
     }
   }
@@ -178,6 +178,8 @@ open_buffer() {
     return false;
   }
 
+  _egl_display = eglgsg->_egl_display;
+
   int attrib_list[] = {
     EGL_WIDTH, _size.get_x(),
     EGL_HEIGHT, _size.get_y(),

+ 8 - 0
panda/src/egldisplay/eglGraphicsPipe.I

@@ -10,3 +10,11 @@
  * @author rdb
  * @date 2009-05-21
  */
+
+/**
+ *
+ */
+INLINE EGLDisplay eglGraphicsPipe::
+get_egl_display() const {
+  return _egl_display;
+}

+ 44 - 3
panda/src/egldisplay/eglGraphicsPipe.cxx

@@ -25,19 +25,39 @@ TypeHandle eglGraphicsPipe::_type_handle;
  *
  */
 eglGraphicsPipe::
-eglGraphicsPipe(const std::string &display) : x11GraphicsPipe(display) {
+eglGraphicsPipe() {
+  //NB. if the X11 display failed to open, _display will be 0, which is a valid
+  // input to eglGetDisplay - it means to open the default display.
+#ifdef HAVE_X11
   _egl_display = eglGetDisplay((NativeDisplayType) _display);
+#else
+  _egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+#endif
   if (!eglInitialize(_egl_display, nullptr, nullptr)) {
     egldisplay_cat.error()
       << "Couldn't initialize the EGL display: "
       << get_egl_error_string(eglGetError()) << "\n";
+    _is_valid = false;
+    return;
   }
 
+#if defined(OPENGLES_1) || defined(OPENGLES_2)
   if (!eglBindAPI(EGL_OPENGL_ES_API)) {
     egldisplay_cat.error()
       << "Couldn't bind EGL to the OpenGL ES API: "
       << get_egl_error_string(eglGetError()) << "\n";
+#else
+  if (!eglBindAPI(EGL_OPENGL_API)) {
+    egldisplay_cat.error()
+      << "Couldn't bind EGL to the OpenGL API: "
+      << get_egl_error_string(eglGetError()) << "\n";
+#endif
+    _is_valid = false;
+    return;
   }
+
+  // Even if we don't have an X11 display, we can still render headless.
+  _is_valid = true;
 }
 
 /**
@@ -61,7 +81,11 @@ eglGraphicsPipe::
  */
 std::string eglGraphicsPipe::
 get_interface_name() const {
+#if defined(OPENGLES_1) || defined(OPENGLES_2)
   return "OpenGL ES";
+#else
+  return "OpenGL";
+#endif
 }
 
 /**
@@ -110,6 +134,10 @@ make_output(const std::string &name,
   // First thing to try: an eglGraphicsWindow
 
   if (retry == 0) {
+#ifdef HAVE_X11
+    if (!_display) {
+      return nullptr;
+    }
     if (((flags&BF_require_parasite)!=0)||
         ((flags&BF_refuse_window)!=0)||
         ((flags&BF_resizeable)!=0)||
@@ -121,9 +149,12 @@ make_output(const std::string &name,
     }
     return new eglGraphicsWindow(engine, this, name, fb_prop, win_prop,
                                  flags, gsg, host);
+#else
+    return nullptr;
+#endif
   }
 
-  // Second thing to try: a GLES(2)GraphicsBuffer
+  // Second thing to try: a GL(ES(2))GraphicsBuffer
   if (retry == 1) {
     if ((host==0)||
   // (!gl_support_fbo)||
@@ -154,9 +185,12 @@ make_output(const std::string &name,
 #ifdef OPENGLES_2
     return new GLES2GraphicsBuffer(engine, this, name, fb_prop, win_prop,
                                   flags, gsg, host);
-#else
+#elif defined(OPENGLES_1)
     return new GLESGraphicsBuffer(engine, this, name, fb_prop, win_prop,
                                   flags, gsg, host);
+#else
+    return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
+                                flags, gsg, host);
 #endif
   }
 
@@ -184,6 +218,10 @@ make_output(const std::string &name,
 
   // Fourth thing to try: an eglGraphicsPixmap.
   if (retry == 3) {
+#ifdef HAVE_X11
+    if (!_display) {
+      return nullptr;
+    }
     if (((flags&BF_require_parasite)!=0)||
         ((flags&BF_require_window)!=0)||
         ((flags&BF_resizeable)!=0)||
@@ -198,6 +236,9 @@ make_output(const std::string &name,
 
     return new eglGraphicsPixmap(engine, this, name, fb_prop, win_prop,
                                  flags, gsg, host);
+#else
+    return nullptr;
+#endif
   }
 
   // Nothing else left to try.

+ 20 - 10
panda/src/egldisplay/eglGraphicsPipe.h

@@ -15,7 +15,14 @@
 #define EGLGRAPHICSPIPE_H
 
 #include "pandabase.h"
+
+#ifdef HAVE_X11
 #include "x11GraphicsPipe.h"
+typedef x11GraphicsPipe BaseGraphicsPipe;
+#else
+#include "graphicsPipe.h"
+typedef GraphicsPipe BaseGraphicsPipe;
+#endif
 
 #ifdef OPENGLES_2
   #include "gles2gsg.h"
@@ -25,11 +32,16 @@
   #define NativeDisplayType EGLNativeDisplayType
   #define NativePixmapType EGLNativePixmapType
   #define NativeWindowType EGLNativeWindowType
-#else
+#elif defined(OPENGLES_1)
   #include "glesgsg.h"
   #include "pre_x11_include.h"
   #include <GLES/egl.h>
   #include "post_x11_include.h"
+#else
+  #include "glgsg.h"
+  #include "pre_x11_include.h"
+  #include <EGL/egl.h>
+  #include "post_x11_include.h"
 #endif
 
 class FrameBufferProperties;
@@ -42,14 +54,16 @@ class eglGraphicsWindow;
  * This graphics pipe represents the interface for creating OpenGL ES graphics
  * windows on an X-based (e.g.  Unix) client.
  */
-class eglGraphicsPipe : public x11GraphicsPipe {
+class eglGraphicsPipe : public BaseGraphicsPipe {
 public:
-  eglGraphicsPipe(const std::string &display = std::string());
+  eglGraphicsPipe();
   virtual ~eglGraphicsPipe();
 
   virtual std::string get_interface_name() const;
   static PT(GraphicsPipe) pipe_constructor();
 
+  INLINE EGLDisplay get_egl_display() const;
+
 protected:
   virtual PT(GraphicsOutput) make_output(const std::string &name,
                                          const FrameBufferProperties &fb_prop,
@@ -62,16 +76,16 @@ protected:
                                          bool &precertify);
 
 private:
-  EGLDisplay _egl_display;
+  EGLDisplay _egl_display = 0;
 
 public:
   static TypeHandle get_class_type() {
     return _type_handle;
   }
   static void init_type() {
-    x11GraphicsPipe::init_type();
+    BaseGraphicsPipe::init_type();
     register_type(_type_handle, "eglGraphicsPipe",
-                  x11GraphicsPipe::get_class_type());
+                  BaseGraphicsPipe::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -80,10 +94,6 @@ public:
 
 private:
   static TypeHandle _type_handle;
-
-  friend class eglGraphicsBuffer;
-  friend class eglGraphicsPixmap;
-  friend class eglGraphicsWindow;
 };
 
 #include "eglGraphicsPipe.I"

+ 9 - 4
panda/src/egldisplay/eglGraphicsPixmap.cxx

@@ -12,6 +12,9 @@
  */
 
 #include "eglGraphicsPixmap.h"
+
+#ifdef HAVE_X11
+
 #include "eglGraphicsWindow.h"
 #include "eglGraphicsStateGuardian.h"
 #include "config_egldisplay.h"
@@ -37,8 +40,7 @@ eglGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe,
 {
   eglGraphicsPipe *egl_pipe;
   DCAST_INTO_V(egl_pipe, _pipe);
-  _display = egl_pipe->get_display();
-  _egl_display = egl_pipe->_egl_display;
+  _egl_display = egl_pipe->get_egl_display();
   _drawable = None;
   _x_pixmap = None;
   _egl_surface = EGL_NO_SURFACE;
@@ -167,7 +169,7 @@ open_buffer() {
   if (_gsg == 0) {
     // There is no old gsg.  Create a new one.
     eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr);
-    eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true);
+    eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, false, true);
     _gsg = eglgsg;
   } else {
     // If the old gsg has the wrong pixel format, create a new one that shares
@@ -175,7 +177,7 @@ open_buffer() {
     DCAST_INTO_R(eglgsg, _gsg, false);
     if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
       eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
-      eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true);
+      eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, false, true);
       _gsg = eglgsg;
     }
   }
@@ -194,6 +196,7 @@ open_buffer() {
     return false;
   }
 
+  _display = egl_pipe->get_display();
   _drawable = egl_pipe->get_root();
   if (_host != nullptr) {
     if (_host->is_of_type(eglGraphicsWindow::get_class_type())) {
@@ -241,3 +244,5 @@ open_buffer() {
   _is_valid = true;
   return true;
 }
+
+#endif  // HAVE_X11

+ 4 - 0
panda/src/egldisplay/eglGraphicsPixmap.h

@@ -16,6 +16,8 @@
 
 #include "pandabase.h"
 
+#ifdef HAVE_X11
+
 #include "eglGraphicsPipe.h"
 #include "graphicsBuffer.h"
 
@@ -67,4 +69,6 @@ private:
   static TypeHandle _type_handle;
 };
 
+#endif  // HAVE_X11
+
 #endif

+ 63 - 62
panda/src/egldisplay/eglGraphicsStateGuardian.cxx

@@ -25,19 +25,11 @@ TypeHandle eglGraphicsStateGuardian::_type_handle;
 eglGraphicsStateGuardian::
 eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
        eglGraphicsStateGuardian *share_with) :
-#ifdef OPENGLES_2
-  GLES2GraphicsStateGuardian(engine, pipe)
-#else
-  GLESGraphicsStateGuardian(engine, pipe)
-#endif
+  BaseGraphicsStateGuardian(engine, pipe)
 {
   _share_context=0;
   _context=0;
-  _display=0;
   _egl_display=0;
-  _screen=0;
-  _visual=0;
-  _visuals=0;
   _fbconfig=0;
 
   if (share_with != nullptr) {
@@ -51,9 +43,6 @@ eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
  */
 eglGraphicsStateGuardian::
 ~eglGraphicsStateGuardian() {
-  if (_visuals != nullptr) {
-    XFree(_visuals);
-  }
   if (_context != (EGLContext)nullptr) {
     if (!eglDestroyContext(_egl_display, _context)) {
       egldisplay_cat.error() << "Failed to destroy EGL context: "
@@ -108,11 +97,6 @@ get_properties(FrameBufferProperties &properties,
     slow = true;
   }
 
-  if ((surface_type & EGL_WINDOW_BIT)==0) {
-    // We insist on having a context that will support an onscreen window.
-    return;
-  }
-
   properties.set_back_buffers(1);
   properties.set_rgb_color(1);
   properties.set_rgba_bits(red_size, green_size, blue_size, alpha_size);
@@ -131,26 +115,23 @@ get_properties(FrameBufferProperties &properties,
  */
 void eglGraphicsStateGuardian::
 choose_pixel_format(const FrameBufferProperties &properties,
-        X11_Display *display,
-        int screen, bool need_pbuffer, bool need_pixmap) {
+                    eglGraphicsPipe *egl_pipe, bool need_window,
+                    bool need_pbuffer, bool need_pixmap) {
 
-  _display = display;
-  _egl_display = eglGetDisplay((NativeDisplayType) display);
-  _screen = screen;
+  _egl_display = egl_pipe->get_egl_display();
   _context = 0;
   _fbconfig = 0;
-  _visual = 0;
-  _visuals = 0;
   _fbprops.clear();
 
   int attrib_list[] = {
-#ifdef OPENGLES_1
+#if defined(OPENGLES_1)
     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
-#endif
-#ifdef OPENGLES_2
+#elif defined(OPENGLES_2)
     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+#else
+    EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
 #endif
-    EGL_SURFACE_TYPE, EGL_DONT_CARE,
+    EGL_SURFACE_TYPE, need_window ? EGL_WINDOW_BIT : EGL_DONT_CARE,
     EGL_NONE
   };
 
@@ -206,23 +187,56 @@ choose_pixel_format(const FrameBufferProperties &properties,
       best_props = fbprops;
     }
   }
-  int depth = DefaultDepth(_display, _screen);
-  _visual = new XVisualInfo;
-  XMatchVisualInfo(_display, _screen, depth, TrueColor, _visual);
+#ifdef HAVE_X11
+  X11_Display *display = egl_pipe->get_display();
+  if (display) {
+    int screen = egl_pipe->get_screen();
+    int depth = DefaultDepth(display, screen);
+    _visual = new XVisualInfo;
+    XMatchVisualInfo(display, screen, depth, TrueColor, _visual);
+  }
+#endif
 
   if (best_quality > 0) {
     egldisplay_cat.debug()
       << "Chosen config " << best_result << ": " << best_props << "\n";
     _fbconfig = configs[best_result];
+
+    EGLint attribs[32];
+    int n = 0;
+
 #ifdef OPENGLES_2
-    EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
-    _context = eglCreateContext(_egl_display, _fbconfig, _share_context, context_attribs);
-#else
-    _context = eglCreateContext(_egl_display, _fbconfig, _share_context, nullptr);
+    attribs[n++] = EGL_CONTEXT_CLIENT_VERSION;
+    attribs[n++] = 2;
+#elif defined(OPENGLES_1)
+#else  // Regular OpenGL
+    if (gl_version.get_num_words() > 0) {
+      attribs[n++] = EGL_CONTEXT_MAJOR_VERSION;
+      attribs[n++] = gl_version[0];
+      if (gl_version.get_num_words() > 1) {
+        attribs[n++] = EGL_CONTEXT_MINOR_VERSION;
+        attribs[n++] = gl_version[1];
+      }
+    }
+    if (gl_debug) {
+      attribs[n++] = EGL_CONTEXT_OPENGL_DEBUG;
+      attribs[n++] = EGL_TRUE;
+    }
+    if (gl_forward_compatible) {
+      attribs[n++] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE;
+      attribs[n++] = EGL_TRUE;
+    }
 #endif
+    attribs[n] = EGL_NONE;
+
+    _context = eglCreateContext(_egl_display, _fbconfig, _share_context, (n > 0) ? attribs : nullptr);
+
     int err = eglGetError();
     if (_context && err == EGL_SUCCESS) {
-      if (_visual) {
+#ifdef HAVE_X11
+      if (!display || _visual)
+#endif
+      {
         _fbprops = best_props;
         delete[] configs;
         return;
@@ -234,8 +248,9 @@ choose_pixel_format(const FrameBufferProperties &properties,
       << get_egl_error_string(err) << "\n";
     _fbconfig = 0;
     _context = 0;
+#ifdef HAVE_X11
     _visual = 0;
-    _visuals = 0;
+#endif
   }
 
   egldisplay_cat.error() <<
@@ -249,18 +264,9 @@ choose_pixel_format(const FrameBufferProperties &properties,
  */
 void eglGraphicsStateGuardian::
 reset() {
-#ifdef OPENGLES_2
-  GLES2GraphicsStateGuardian::reset();
-#else
-  GLESGraphicsStateGuardian::reset();
-#endif
+  BaseGraphicsStateGuardian::reset();
 
-  // If "Mesa" is present, assume software.  However, if "Mesa DRI" is found,
-  // it's actually a Mesa-based OpenGL layer running over a hardware driver.
-  if (_gl_renderer == "Software Rasterizer" ||
-      (_gl_renderer.find("Mesa") != std::string::npos &&
-       _gl_renderer.find("Mesa DRI") == std::string::npos)) {
-    // It's Mesa, therefore probably a software context.
+  if (_gl_renderer == "Software Rasterizer") {
     _fbprops.set_force_software(1);
     _fbprops.set_force_hardware(0);
   } else {
@@ -289,13 +295,11 @@ egl_is_at_least_version(int major_version, int minor_version) const {
  */
 void eglGraphicsStateGuardian::
 gl_flush() const {
+#ifdef HAVE_X11
   // This call requires synchronization with X.
   LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
-#ifdef OPENGLES_2
-  GLES2GraphicsStateGuardian::gl_flush();
-#else
-  GLESGraphicsStateGuardian::gl_flush();
 #endif
+  BaseGraphicsStateGuardian::gl_flush();
 }
 
 /**
@@ -303,13 +307,11 @@ gl_flush() const {
  */
 GLenum eglGraphicsStateGuardian::
 gl_get_error() const {
+#ifdef HAVE_X11
   // This call requires synchronization with X.
   LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
-#ifdef OPENGLES_2
-  return GLES2GraphicsStateGuardian::gl_get_error();
-#else
-  return GLESGraphicsStateGuardian::gl_get_error();
 #endif
+  return BaseGraphicsStateGuardian::gl_get_error();
 }
 
 /**
@@ -317,11 +319,7 @@ gl_get_error() const {
  */
 void eglGraphicsStateGuardian::
 query_gl_version() {
-#ifdef OPENGLES_2
-  GLES2GraphicsStateGuardian::query_gl_version();
-#else
-  GLESGraphicsStateGuardian::query_gl_version();
-#endif
+  BaseGraphicsStateGuardian::query_gl_version();
 
   // Calling eglInitialize on an already-initialized display will just provide
   // us the version numbers.
@@ -336,9 +334,12 @@ query_gl_version() {
 #ifdef OPENGLES_2
   if (gles2gsg_cat.is_debug()) {
     gles2gsg_cat.debug()
-#else
+#elif defined(OPENGLES_1)
   if (glesgsg_cat.is_debug()) {
     glesgsg_cat.debug()
+#else
+  if (glgsg_cat.is_debug()) {
+    glgsg_cat.debug()
 #endif
       << "EGL_VERSION = " << _egl_version_major << "." << _egl_version_minor
       << "\n";

+ 19 - 20
panda/src/egldisplay/eglGraphicsStateGuardian.h

@@ -16,26 +16,32 @@
 
 #include "pandabase.h"
 #include "eglGraphicsPipe.h"
+
+#ifdef HAVE_X11
 #include "get_x11.h"
+#endif
+
+#ifdef OPENGLES_2
+typedef GLES2GraphicsStateGuardian BaseGraphicsStateGuardian;
+#elif defined(OPENGLES_1)
+typedef GLESGraphicsStateGuardian BaseGraphicsStateGuardian;
+#else
+typedef GLGraphicsStateGuardian BaseGraphicsStateGuardian;
+#endif
 
 /**
  * A tiny specialization on GLESGraphicsStateGuardian to add some egl-specific
  * information.
  */
-#ifdef OPENGLES_2
-class eglGraphicsStateGuardian : public GLES2GraphicsStateGuardian {
-#else
-class eglGraphicsStateGuardian : public GLESGraphicsStateGuardian {
-#endif
+class eglGraphicsStateGuardian : public BaseGraphicsStateGuardian {
 public:
   INLINE const FrameBufferProperties &get_fb_properties() const;
   void get_properties(FrameBufferProperties &properties,
              bool &pbuffer_supported, bool &pixmap_supported,
                                bool &slow, EGLConfig config);
   void choose_pixel_format(const FrameBufferProperties &properties,
-         X11_Display *_display,
-         int _screen,
-         bool need_pbuffer, bool need_pixmap);
+                           eglGraphicsPipe *egl_pipe, bool need_window,
+                           bool need_pbuffer, bool need_pixmap);
 
   eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
          eglGraphicsStateGuardian *share_with);
@@ -49,10 +55,9 @@ public:
   EGLContext _share_context;
   EGLContext _context;
   EGLDisplay _egl_display;
-  X11_Display *_display;
-  int _screen;
-  XVisualInfo *_visual;
-  XVisualInfo *_visuals;
+#ifdef HAVE_X11
+  XVisualInfo *_visual = nullptr;
+#endif
   EGLConfig _fbconfig;
   FrameBufferProperties _fbprops;
 
@@ -72,15 +77,9 @@ public:
     return _type_handle;
   }
   static void init_type() {
-#ifdef OPENGLES_2
-    GLES2GraphicsStateGuardian::init_type();
+    BaseGraphicsStateGuardian::init_type();
     register_type(_type_handle, "eglGraphicsStateGuardian",
-                  GLES2GraphicsStateGuardian::get_class_type());
-#else
-    GLESGraphicsStateGuardian::init_type();
-    register_type(_type_handle, "eglGraphicsStateGuardian",
-                  GLESGraphicsStateGuardian::get_class_type());
-#endif
+                  BaseGraphicsStateGuardian::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();

+ 8 - 3
panda/src/egldisplay/eglGraphicsWindow.cxx

@@ -12,6 +12,9 @@
  */
 
 #include "eglGraphicsWindow.h"
+
+#ifdef HAVE_X11
+
 #include "eglGraphicsStateGuardian.h"
 #include "config_egldisplay.h"
 #include "eglGraphicsPipe.h"
@@ -44,7 +47,7 @@ eglGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
 {
   eglGraphicsPipe *egl_pipe;
   DCAST_INTO_V(egl_pipe, _pipe);
-  _egl_display = egl_pipe->_egl_display;
+  _egl_display = egl_pipe->get_egl_display();
   _egl_surface = 0;
 }
 
@@ -206,7 +209,7 @@ open_window() {
   if (_gsg == 0) {
     // There is no old gsg.  Create a new one.
     eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr);
-    eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false);
+    eglgsg->choose_pixel_format(_fb_properties, egl_pipe, true, false, false);
     _gsg = eglgsg;
   } else {
     // If the old gsg has the wrong pixel format, create a new one that shares
@@ -214,7 +217,7 @@ open_window() {
     DCAST_INTO_R(eglgsg, _gsg, false);
     if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
       eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
-      eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false);
+      eglgsg->choose_pixel_format(_fb_properties, egl_pipe, true, false, false);
       _gsg = eglgsg;
     }
   }
@@ -258,3 +261,5 @@ open_window() {
 
   return true;
 }
+
+#endif  // HAVE_X11

+ 4 - 0
panda/src/egldisplay/eglGraphicsWindow.h

@@ -16,6 +16,8 @@
 
 #include "pandabase.h"
 
+#ifdef HAVE_X11
+
 #include "eglGraphicsPipe.h"
 #include "x11GraphicsWindow.h"
 
@@ -65,4 +67,6 @@ private:
 
 #include "eglGraphicsWindow.I"
 
+#endif  // HAVE_X11
+
 #endif

+ 8 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1283,10 +1283,12 @@ reset() {
   // Note that these extensions only offer support for GL_BGRA, not GL_BGR.
   _supports_bgr = has_extension("GL_EXT_texture_format_BGRA8888") ||
                   has_extension("GL_APPLE_texture_format_BGRA8888");
+  _supports_bgra_read = has_extension("GL_EXT_read_format_bgra");
 #else
   // In regular OpenGL, we have both GL_BGRA and GL_BGR.
   _supports_bgr =
     is_at_least_gl_version(1, 2) || has_extension("GL_EXT_bgra");
+  _supports_bgra_read = _supports_bgr;
 #endif
 
 #ifdef SUPPORT_FIXED_FUNCTION
@@ -7436,6 +7438,12 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
 
   GLenum external_format = get_external_image_format(tex);
 
+  // OpenGL ES implementations may support BGRA, but that doesn't imply they
+  // also support it for glReadPixels specifically.
+  if (!_supports_bgra_read && external_format == GL_BGRA) {
+    external_format = GL_RGBA;
+  }
+
   if (GLCAT.is_spam()) {
     GLCAT.spam()
       << "glReadPixels(" << xo << ", " << yo << ", " << w << ", " << h << ", ";

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

@@ -815,6 +815,7 @@ public:
   PFNGLGETCOMPRESSEDTEXIMAGEPROC _glGetCompressedTexImage;
 
   bool _supports_bgr;
+  bool _supports_bgra_read;
   bool _supports_packed_dabc;
   bool _supports_packed_ufloat;
 

+ 4 - 4
panda/src/grutil/meshDrawer2D.I

@@ -60,7 +60,7 @@ set_budget(int total_budget) {
 }
 
 /**
- * Gets the total triangle budget of the drawer
+ * Gets the total triangle budget of the drawer.
  */
 INLINE int MeshDrawer2D::
 get_budget() {
@@ -68,7 +68,7 @@ get_budget() {
 }
 
 /**
- * Sets clipping rectangle
+ * Sets the clipping rectangle.
  */
 INLINE void MeshDrawer2D::
 set_clip(PN_stdfloat x, PN_stdfloat y, PN_stdfloat w, PN_stdfloat h) {
@@ -79,7 +79,7 @@ set_clip(PN_stdfloat x, PN_stdfloat y, PN_stdfloat w, PN_stdfloat h) {
 }
 
 /**
- * Draws a 2d rectangle.  Ignores the cliping rectangle
+ * Draws a 2D rectangle.  Ignores the clipping rectangle.
  */
 INLINE void MeshDrawer2D::
 quad_raw(const LVector3 &v1, const LVector4 &c1, const LVector2 &uv1,
@@ -125,7 +125,7 @@ rectangle_raw(PN_stdfloat x, PN_stdfloat y, PN_stdfloat w, PN_stdfloat h,
 }
 
 /**
- * Draws a 2d rectangle, that can be cliped
+ * Draws a 2D rectangle which can be clipped.
  */
 INLINE void MeshDrawer2D::
 rectangle(PN_stdfloat x, PN_stdfloat y, PN_stdfloat w, PN_stdfloat h,

+ 2 - 2
panda/src/grutil/meshDrawer2D.h

@@ -39,8 +39,8 @@
 #include "nodePath.h"
 
 /**
- * This class allows the drawing of 2d objects - mainly based on quads and
- * rectangles.  Allows clipping and serverl high level UI theme functions.
+ * This class allows the drawing of 2D objects - mainly based on quads and
+ * rectangles.  It allows clipping and several high level UI theme functions.
  */
 class EXPCL_PANDA_GRUTIL MeshDrawer2D : public TypedObject {
 PUBLISHED:

+ 12 - 4
panda/src/nativenet/buffered_datagramconnection.h

@@ -136,7 +136,10 @@ private:
  * used to do a full reset of buffers
  */
 inline void Buffered_DatagramConnection::ClearAll(void) {
-  nativenet_cat.error() << "Buffered_DatagramConnection::ClearAll Starting Auto Reset\n";
+  if (nativenet_cat.is_debug()) {
+    nativenet_cat.debug()
+      << "Buffered_DatagramConnection::ClearAll Starting Auto Reset\n";
+  }
   Close();
   _Writer.ReSet();
   _Reader.ReSet();
@@ -215,8 +218,11 @@ inline Buffered_DatagramConnection::~Buffered_DatagramConnection(void)
 inline Buffered_DatagramConnection::Buffered_DatagramConnection(int rbufsize, int wbufsize, int write_flush_point)
     :  _Writer(wbufsize,write_flush_point) , _Reader(rbufsize)
 {
-  nativenet_cat.error() << "Buffered_DatagramConnection Constructor rbufsize = " << rbufsize
-                        << " wbufsize = " << wbufsize << " write_flush_point = " << write_flush_point << "\n";
+  if (nativenet_cat.is_debug()) {
+    nativenet_cat.debug()
+      << "Buffered_DatagramConnection Constructor rbufsize = " << rbufsize
+      << " wbufsize = " << wbufsize << " write_flush_point = " << write_flush_point << "\n";
+  }
 }
 
 inline bool  Buffered_DatagramConnection::SendMessageBufferOnly(Datagram &msg)
@@ -289,7 +295,9 @@ bool Buffered_DatagramConnection::Flush(void)
  * Reset
  */
 inline void Buffered_DatagramConnection::Reset() {
-  nativenet_cat.error() << "Buffered_DatagramConnection::Reset()\n";
+  if (nativenet_cat.is_debug()) {
+    nativenet_cat.debug() << "Buffered_DatagramConnection::Reset()\n";
+  }
   ClearAll();
 }
 

+ 7 - 5
panda/src/pgraph/geomNode.cxx

@@ -507,8 +507,10 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
       << " draw_mask = " << data._draw_mask << "\n";
   }
 
+  Thread *current_thread = trav->get_current_thread();
+
   // Get all the Geoms, with no decalling.
-  Geoms geoms = get_geoms(trav->get_current_thread());
+  Geoms geoms = get_geoms(current_thread);
   int num_geoms = geoms.get_num_geoms();
   trav->_geoms_pcollector.add_level(num_geoms);
   CPT(TransformState) internal_transform = data.get_internal_transform(trav);
@@ -532,9 +534,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
     if (num_geoms > 1) {
       if (data._view_frustum != nullptr) {
         // Cull the individual Geom against the view frustum.
-        CPT(BoundingVolume) geom_volume = geom->get_bounds();
+        CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
         const GeometricBoundingVolume *geom_gbv =
-          DCAST(GeometricBoundingVolume, geom_volume);
+          geom_volume->as_geometric_bounding_volume();
 
         int result = data._view_frustum->contains(geom_gbv);
         if (result == BoundingVolume::IF_no_intersection) {
@@ -544,9 +546,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
       }
       if (!data._cull_planes->is_empty()) {
         // Also cull the Geom against the cull planes.
-        CPT(BoundingVolume) geom_volume = geom->get_bounds();
+        CPT(BoundingVolume) geom_volume = geom->get_bounds(current_thread);
         const GeometricBoundingVolume *geom_gbv =
-          DCAST(GeometricBoundingVolume, geom_volume);
+          geom_volume->as_geometric_bounding_volume();
         int result;
         data._cull_planes->do_cull(result, state, geom_gbv);
         if (result == BoundingVolume::IF_no_intersection) {

+ 6 - 0
panda/src/pgraph/pandaNode_ext.cxx

@@ -165,6 +165,12 @@ clear_python_tag(PyObject *key) {
   if (PyDict_GetItem(dict, key) != nullptr) {
     PyDict_DelItem(dict, key);
   }
+
+  if (PyDict_Size(dict) == 0 && Py_REFCNT(dict) == 1) {
+    // This was the last tag, and do_get_python_tags() made sure we have a
+    // unique reference to the tags, so clear the tag object.
+    _this->_python_tag_data.clear();
+  }
 }
 
 /**

+ 3 - 0
pandatool/src/deploy-stub/deploy-stub.c

@@ -655,6 +655,9 @@ int main(int argc, char *argv[]) {
   PyImport_FrozenModules = blobinfo.pointers[0];
   retval = Py_FrozenMain(argc, argv);
 
+  fflush(stdout);
+  fflush(stderr);
+
   unmap_blob(blob);
   return retval;
 }

+ 0 - 1
samples/fireflies/light.sha

@@ -14,7 +14,6 @@ void vshader(float4 vtx_position : POSITION,
 }
 
 void fshader(float4 l_pos: TEXCOORD0,
-             float4 l_scale: TEXCOORD1,
              uniform sampler2D k_texnormal : TEXUNIT0,
              uniform sampler2D k_texalbedo : TEXUNIT1,
              uniform sampler2D k_texdepth  : TEXUNIT2,

+ 29 - 0
tests/pgraph/test_nodepath.py

@@ -194,6 +194,35 @@ def test_nodepath_python_tags():
     assert rc1 == rc2
 
 
+def test_nodepath_clear_python_tag():
+    from panda3d.core import NodePath
+
+    path = NodePath("node")
+    assert not path.has_python_tag("a")
+    assert not path.has_python_tag("b")
+    assert not path.node().has_tags()
+
+    path.set_python_tag("a", "value")
+    assert path.has_python_tag("a")
+    assert not path.has_python_tag("b")
+    assert path.node().has_tags()
+
+    path.set_python_tag("b", "value")
+    assert path.has_python_tag("a")
+    assert path.has_python_tag("b")
+    assert path.node().has_tags()
+
+    path.clear_python_tag("a")
+    assert not path.has_python_tag("a")
+    assert path.has_python_tag("b")
+    assert path.node().has_tags()
+
+    path.clear_python_tag("b")
+    assert not path.has_python_tag("a")
+    assert not path.has_python_tag("b")
+    assert not path.node().has_tags()
+
+
 def test_nodepath_replace_texture():
     from panda3d.core import NodePath, Texture
 

+ 3 - 2
tests/putil/test_bitarray.py

@@ -129,12 +129,13 @@ def test_bitarray_has_any_of():
     ba = BitArray()
     assert not ba.has_any_of(100, 200)
 
-    ba = BitArray(0x001fffffffffffff)
+    ba = BitArray()
+    ba.set_range(0, 53)
     assert ba.has_any_of(52, 1)
     assert ba.has_any_of(52, 100)
     assert not ba.has_any_of(53, 45)
 
-    ba = BitArray(0)
+    ba = BitArray()
     ba.invert_in_place()
     assert ba.has_any_of(0, 1)
     assert ba.has_any_of(53, 45)

+ 2 - 2
tests/putil/test_clockobject.py

@@ -16,13 +16,13 @@ def test_clock_jump_frame_time(clockobj):
 def test_clock_get_real_time(clockobj):
     current_time = clockobj.get_real_time()
     time.sleep(0.4)
-    assert clockobj.get_real_time() - current_time >= 0.4
+    assert clockobj.get_real_time() - current_time >= 0.39
 
 
 def test_clock_get_long_time(clockobj):
     current_time = clockobj.get_long_time()
     time.sleep(0.4)
-    assert clockobj.get_long_time() - current_time >= 0.4
+    assert clockobj.get_long_time() - current_time >= 0.39
 
 
 def test_clock_get_dt(clockobj):

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません