Browse Source

Merge branch 'release/1.10.x'

rdb 6 years ago
parent
commit
bc563c8664

+ 2 - 0
direct/src/directtools/DirectUtil.py

@@ -1,5 +1,7 @@
 
 
 from .DirectGlobals import *
 from .DirectGlobals import *
+from panda3d.core import VBase4
+from direct.task.Task import Task
 
 
 # Routines to adjust values
 # Routines to adjust values
 def ROUND_TO(value, divisor):
 def ROUND_TO(value, divisor):

+ 6 - 1
direct/src/gui/DirectScrolledFrame.py

@@ -33,7 +33,7 @@ class DirectScrolledFrame(DirectFrame):
             ('canvasSize',     (-1, 1, -1, 1),        self.setCanvasSize),
             ('canvasSize',     (-1, 1, -1, 1),        self.setCanvasSize),
             ('manageScrollBars', 1,                self.setManageScrollBars),
             ('manageScrollBars', 1,                self.setManageScrollBars),
             ('autoHideScrollBars', 1,              self.setAutoHideScrollBars),
             ('autoHideScrollBars', 1,              self.setAutoHideScrollBars),
-            ('scrollBarWidth', 0.08,               None),
+            ('scrollBarWidth', 0.08,               self.setScrollBarWidth),
             ('borderWidth',    (0.01, 0.01),       self.setBorderWidth),
             ('borderWidth',    (0.01, 0.01),       self.setBorderWidth),
             )
             )
 
 
@@ -72,6 +72,11 @@ class DirectScrolledFrame(DirectFrame):
         # Call option initialization functions
         # Call option initialization functions
         self.initialiseoptions(DirectScrolledFrame)
         self.initialiseoptions(DirectScrolledFrame)
 
 
+    def setScrollBarWidth(self):
+        w = self['scrollBarWidth']
+        self.verticalScroll["frameSize"] = (-w / 2.0, w / 2.0, -1, 1)
+        self.horizontalScroll["frameSize"] = (-1, 1, -w / 2.0, w / 2.0)
+
     def setCanvasSize(self):
     def setCanvasSize(self):
         f = self['canvasSize']
         f = self['canvasSize']
         self.guiItem.setVirtualFrame(f[0], f[1], f[2], f[3])
         self.guiItem.setVirtualFrame(f[0], f[1], f[2], f[3])

+ 13 - 11
dtool/src/prc/notify.cxx

@@ -19,6 +19,7 @@
 #include "filename.h"
 #include "filename.h"
 #include "config_prc.h"
 #include "config_prc.h"
 
 
+#include <atomic>
 #include <ctype.h>
 #include <ctype.h>
 
 
 #ifdef BUILD_IPHONE
 #ifdef BUILD_IPHONE
@@ -422,28 +423,29 @@ string_severity(const string &str) {
  */
  */
 void Notify::
 void Notify::
 config_initialized() {
 config_initialized() {
-  static bool already_initialized = false;
-  if (already_initialized) {
-    nout << "Notify::config_initialized() called more than once.\n";
-    return;
-  }
-  already_initialized = true;
+  // We allow this to be called more than once to allow the user to specify a
+  // notify-output even after the initial import of Panda3D modules.  However,
+  // it cannot be changed after the first time it is set.
 
 
   if (_ostream_ptr == &cerr) {
   if (_ostream_ptr == &cerr) {
-    ConfigVariableFilename notify_output
+    static ConfigVariableFilename notify_output
       ("notify-output", "",
       ("notify-output", "",
        "The filename to which to write all the output of notify");
        "The filename to which to write all the output of notify");
 
 
-    if (!notify_output.empty()) {
-      if (notify_output == "stdout") {
+    // We use this to ensure that only one thread can initialize the output.
+    static std::atomic_flag initialized = ATOMIC_FLAG_INIT;
+
+    std::string value = notify_output.get_value();
+    if (!value.empty() && !initialized.test_and_set()) {
+      if (value == "stdout") {
         cout.setf(std::ios::unitbuf);
         cout.setf(std::ios::unitbuf);
         set_ostream_ptr(&cout, false);
         set_ostream_ptr(&cout, false);
 
 
-      } else if (notify_output == "stderr") {
+      } else if (value == "stderr") {
         set_ostream_ptr(&cerr, false);
         set_ostream_ptr(&cerr, false);
 
 
       } else {
       } else {
-        Filename filename = notify_output;
+        Filename filename = value;
         filename.set_text();
         filename.set_text();
 #ifdef BUILD_IPHONE
 #ifdef BUILD_IPHONE
         // On the iPhone, route everything through cerr, and then send cerr to
         // On the iPhone, route everything through cerr, and then send cerr to

+ 6 - 0
dtool/src/prc/notifyCategory.cxx

@@ -181,10 +181,16 @@ update_severity_cache() {
     } else {
     } else {
       // Unless, of course, we're the root.
       // Unless, of course, we're the root.
       _severity_cache = NS_info;
       _severity_cache = NS_info;
+
+      // Take this opportunity to have Notify check whether the notify-output
+      // variable changed.
+      Notify::ptr()->config_initialized();
     }
     }
   } else {
   } else {
     _severity_cache = _severity;
     _severity_cache = _severity;
+    Notify::ptr()->config_initialized();
   }
   }
+
   mark_cache_valid(_local_modified);
   mark_cache_valid(_local_modified);
 }
 }
 
 

+ 6 - 2
panda/src/audiotraits/openalAudioManager.cxx

@@ -252,7 +252,9 @@ select_audio_device() {
     devices = (const char *)alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
     devices = (const char *)alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
 
 
     if (devices) {
     if (devices) {
-      audio_cat.debug() << "All OpenAL devices:\n";
+      if (audio_cat.is_debug()) {
+        audio_cat.debug() << "All OpenAL devices:\n";
+      }
 
 
       while (*devices) {
       while (*devices) {
         string device(devices);
         string device(devices);
@@ -280,7 +282,9 @@ select_audio_device() {
     devices = (const char *)alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
     devices = (const char *)alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
 
 
     if (devices) {
     if (devices) {
-      audio_cat.debug() << "OpenAL drivers:\n";
+      if (audio_cat.is_debug()) {
+        audio_cat.debug() << "OpenAL drivers:\n";
+      }
 
 
       while (*devices) {
       while (*devices) {
         string device(devices);
         string device(devices);

+ 18 - 6
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -778,7 +778,9 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
     }
     }
 
 
     if (attachpoint == GL_DEPTH_ATTACHMENT_EXT) {
     if (attachpoint == GL_DEPTH_ATTACHMENT_EXT) {
-      GLCAT.debug() << "Binding texture " << *tex << " to depth attachment.\n";
+      if (GLCAT.is_debug()) {
+        GLCAT.debug() << "Binding texture " << *tex << " to depth attachment.\n";
+      }
 
 
       attach_tex(layer, 0, tex, GL_DEPTH_ATTACHMENT_EXT);
       attach_tex(layer, 0, tex, GL_DEPTH_ATTACHMENT_EXT);
 
 
@@ -789,7 +791,9 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
 #endif
 #endif
 
 
       if (slot == RTP_depth_stencil) {
       if (slot == RTP_depth_stencil) {
-        GLCAT.debug() << "Binding texture " << *tex << " to stencil attachment.\n";
+        if (GLCAT.is_debug()) {
+          GLCAT.debug() << "Binding texture " << *tex << " to stencil attachment.\n";
+        }
 
 
         attach_tex(layer, 0, tex, GL_STENCIL_ATTACHMENT_EXT);
         attach_tex(layer, 0, tex, GL_STENCIL_ATTACHMENT_EXT);
 
 
@@ -801,7 +805,9 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
       }
       }
 
 
     } else {
     } else {
-      GLCAT.debug() << "Binding texture " << *tex << " to color attachment.\n";
+      if (GLCAT.is_debug()) {
+        GLCAT.debug() << "Binding texture " << *tex << " to color attachment.\n";
+      }
 
 
       attach_tex(layer, 0, tex, attachpoint);
       attach_tex(layer, 0, tex, attachpoint);
 
 
@@ -988,7 +994,9 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
     glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rb[slot]);
     glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rb[slot]);
 
 
     if (slot == RTP_depth_stencil) {
     if (slot == RTP_depth_stencil) {
-      GLCAT.debug() << "Creating depth stencil renderbuffer.\n";
+      if (GLCAT.is_debug()) {
+        GLCAT.debug() << "Creating depth stencil renderbuffer.\n";
+      }
       // Allocate renderbuffer storage for depth stencil.
       // Allocate renderbuffer storage for depth stencil.
       GLint depth_size = 0, stencil_size = 0;
       GLint depth_size = 0, stencil_size = 0;
       glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
       glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
@@ -1014,7 +1022,9 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
       report_my_gl_errors();
       report_my_gl_errors();
 
 
     } else if (slot == RTP_depth) {
     } else if (slot == RTP_depth) {
-      GLCAT.debug() << "Creating depth renderbuffer.\n";
+      if (GLCAT.is_debug()) {
+        GLCAT.debug() << "Creating depth renderbuffer.\n";
+      }
       // Allocate renderbuffer storage for regular depth.
       // Allocate renderbuffer storage for regular depth.
       GLint depth_size = 0;
       GLint depth_size = 0;
       glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
       glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
@@ -1052,7 +1062,9 @@ bind_slot(int layer, bool rb_resize, Texture **attach, RenderTexturePlane slot,
       report_my_gl_errors();
       report_my_gl_errors();
 
 
     } else {
     } else {
-      GLCAT.debug() << "Creating color renderbuffer.\n";
+      if (GLCAT.is_debug()) {
+        GLCAT.debug() << "Creating color renderbuffer.\n";
+      }
       glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
       glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, gl_format, _rb_size_x, _rb_size_y);
 
 
       GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0;
       GLint red_size = 0, green_size = 0, blue_size = 0, alpha_size = 0;

+ 6 - 4
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -722,10 +722,12 @@ reset() {
                    || has_extension("GL_KHR_debug")
                    || has_extension("GL_KHR_debug")
                    || has_extension("GL_ARB_debug_output");
                    || has_extension("GL_ARB_debug_output");
 
 
-    if (_supports_debug) {
-      GLCAT.debug() << "gl-debug supported, but NOT enabled.\n";
-    } else {
-      GLCAT.debug() << "gl-debug disabled and unsupported.\n";
+    if (GLCAT.is_debug()) {
+      if (_supports_debug) {
+        GLCAT.debug() << "gl-debug supported, but NOT enabled.\n";
+      } else {
+        GLCAT.debug() << "gl-debug disabled and unsupported.\n";
+      }
     }
     }
   }
   }
 
 

+ 1 - 1
panda/src/glstuff/glShaderContext_src.cxx

@@ -3306,7 +3306,7 @@ glsl_compile_and_link() {
   }
   }
 
 
   _glgsg->report_my_gl_errors();
   _glgsg->report_my_gl_errors();
-  return true;
+  return valid;
 }
 }
 
 
 #endif  // OPENGLES_1
 #endif  // OPENGLES_1

+ 12 - 6
panda/src/gobj/shader.cxx

@@ -3274,8 +3274,10 @@ load(const Filename &file, ShaderLanguage lang) {
       shader_cat.info()
       shader_cat.info()
         << "Shader " << file << " was modified on disk, reloading.\n";
         << "Shader " << file << " was modified on disk, reloading.\n";
     } else {
     } else {
-      shader_cat.debug()
-        << "Shader " << file << " was found in shader cache.\n";
+      if (shader_cat.is_debug()) {
+        shader_cat.debug()
+          << "Shader " << file << " was found in shader cache.\n";
+      }
       return i->second;
       return i->second;
     }
     }
   }
   }
@@ -3312,8 +3314,10 @@ load(ShaderLanguage lang, const Filename &vertex,
       shader_cat.info()
       shader_cat.info()
         << "Shader was modified on disk, reloading.\n";
         << "Shader was modified on disk, reloading.\n";
     } else {
     } else {
-      shader_cat.debug()
-        << "Shader was found in shader cache.\n";
+      if (shader_cat.is_debug()) {
+        shader_cat.debug()
+          << "Shader was found in shader cache.\n";
+      }
       return i->second;
       return i->second;
     }
     }
   }
   }
@@ -3365,8 +3369,10 @@ load_compute(ShaderLanguage lang, const Filename &fn) {
       shader_cat.info()
       shader_cat.info()
         << "Compute shader " << fn << " was modified on disk, reloading.\n";
         << "Compute shader " << fn << " was modified on disk, reloading.\n";
     } else {
     } else {
-      shader_cat.debug()
-        << "Compute shader " << fn << " was found in shader cache.\n";
+      if (shader_cat.is_debug()) {
+        shader_cat.debug()
+          << "Compute shader " << fn << " was found in shader cache.\n";
+      }
       return i->second;
       return i->second;
     }
     }
   }
   }

+ 2 - 2
panda/src/movies/movieTypeRegistry.cxx

@@ -90,7 +90,7 @@ register_audio_type(MakeAudioFunc func, const string &extensions) {
     if (_audio_type_registry.count(*wi)) {
     if (_audio_type_registry.count(*wi)) {
       movies_cat->warning()
       movies_cat->warning()
         << "Attempt to register multiple audio types with extension " << (*wi) << "\n";
         << "Attempt to register multiple audio types with extension " << (*wi) << "\n";
-    } else {
+    } else if (movies_cat->is_debug()) {
       movies_cat->debug()
       movies_cat->debug()
         << "Registered audio type with extension " << (*wi) << "\n";
         << "Registered audio type with extension " << (*wi) << "\n";
     }
     }
@@ -219,7 +219,7 @@ register_video_type(MakeVideoFunc func, const string &extensions) {
     if (_video_type_registry.count(*wi)) {
     if (_video_type_registry.count(*wi)) {
       movies_cat->warning()
       movies_cat->warning()
         << "Attempt to register multiple video types with extension " << (*wi) << "\n";
         << "Attempt to register multiple video types with extension " << (*wi) << "\n";
-    } else {
+    } else if (movies_cat->is_debug()) {
       movies_cat->debug()
       movies_cat->debug()
         << "Registered video type with extension " << (*wi) << "\n";
         << "Registered video type with extension " << (*wi) << "\n";
     }
     }

+ 51 - 31
panda/src/pnmimagetypes/pnmFileTypePNG.cxx

@@ -227,10 +227,12 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
     }
     }
   }
   }
 
 
-  pnmimage_png_cat.debug()
-    << "width = " << width << " height = " << height << " bit_depth = "
-    << bit_depth << " color_type = " << color_type
-    << " color_space = " << _color_space << "\n";
+  if (pnmimage_png_cat.is_debug()) {
+    pnmimage_png_cat.debug()
+      << "width = " << width << " height = " << height << " bit_depth = "
+      << bit_depth << " color_type = " << color_type
+      << " color_space = " << _color_space << "\n";
+  }
 
 
   _x_size = width;
   _x_size = width;
   _y_size = height;
   _y_size = height;
@@ -242,32 +244,42 @@ Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
 
 
   switch (color_type) {
   switch (color_type) {
   case PNG_COLOR_TYPE_GRAY:
   case PNG_COLOR_TYPE_GRAY:
-    pnmimage_png_cat.debug()
-      << "PNG_COLOR_TYPE_GRAY\n";
+    if (pnmimage_png_cat.is_debug()) {
+      pnmimage_png_cat.debug()
+        << "PNG_COLOR_TYPE_GRAY\n";
+    }
     _num_channels = 1;
     _num_channels = 1;
     break;
     break;
 
 
   case PNG_COLOR_TYPE_GRAY_ALPHA:
   case PNG_COLOR_TYPE_GRAY_ALPHA:
-    pnmimage_png_cat.debug()
-      << "PNG_COLOR_TYPE_GRAY_ALPHA\n";
+    if (pnmimage_png_cat.is_debug()) {
+      pnmimage_png_cat.debug()
+        << "PNG_COLOR_TYPE_GRAY_ALPHA\n";
+    }
     _num_channels = 2;
     _num_channels = 2;
     break;
     break;
 
 
   case PNG_COLOR_TYPE_RGB:
   case PNG_COLOR_TYPE_RGB:
-    pnmimage_png_cat.debug()
-      << "PNG_COLOR_TYPE_RGB\n";
+    if (pnmimage_png_cat.is_debug()) {
+      pnmimage_png_cat.debug()
+        << "PNG_COLOR_TYPE_RGB\n";
+    }
     _num_channels = 3;
     _num_channels = 3;
     break;
     break;
 
 
   case PNG_COLOR_TYPE_RGB_ALPHA:
   case PNG_COLOR_TYPE_RGB_ALPHA:
-    pnmimage_png_cat.debug()
-      << "PNG_COLOR_TYPE_RGB_ALPHA\n";
+    if (pnmimage_png_cat.is_debug()) {
+      pnmimage_png_cat.debug()
+        << "PNG_COLOR_TYPE_RGB_ALPHA\n";
+    }
     _num_channels = 4;
     _num_channels = 4;
     break;
     break;
 
 
   case PNG_COLOR_TYPE_PALETTE:
   case PNG_COLOR_TYPE_PALETTE:
-    pnmimage_png_cat.debug()
-      << "PNG_COLOR_TYPE_PALETTE\n";
+    if (pnmimage_png_cat.is_debug()) {
+      pnmimage_png_cat.debug()
+        << "PNG_COLOR_TYPE_PALETTE\n";
+    }
     png_set_palette_to_rgb(_png);
     png_set_palette_to_rgb(_png);
     _maxval = 255;
     _maxval = 255;
     _num_channels = 3;
     _num_channels = 3;
@@ -566,8 +578,10 @@ write_data(xel *array, xelval *alpha_data) {
   if (png_palette) {
   if (png_palette) {
     if (png_bit_depth <= 8) {
     if (png_bit_depth <= 8) {
       if (compute_palette(palette, array, alpha_data, png_max_palette)) {
       if (compute_palette(palette, array, alpha_data, png_max_palette)) {
-        pnmimage_png_cat.debug()
-          << palette.size() << " colors found.\n";
+        if (pnmimage_png_cat.is_debug()) {
+          pnmimage_png_cat.debug()
+            << palette.size() << " colors found.\n";
+        }
 
 
         int palette_bit_depth = make_png_bit_depth(pm_maxvaltobits(palette.size() - 1));
         int palette_bit_depth = make_png_bit_depth(pm_maxvaltobits(palette.size() - 1));
 
 
@@ -581,10 +595,12 @@ write_data(xel *array, xelval *alpha_data) {
 
 
         if (palette_bit_depth < total_bits ||
         if (palette_bit_depth < total_bits ||
             _maxval != (1 << true_bit_depth) - 1) {
             _maxval != (1 << true_bit_depth) - 1) {
-          pnmimage_png_cat.debug()
-            << "palette bit depth of " << palette_bit_depth
-            << " improves on bit depth of " << total_bits
-            << "; making a palette image.\n";
+          if (pnmimage_png_cat.is_debug()) {
+            pnmimage_png_cat.debug()
+              << "palette bit depth of " << palette_bit_depth
+              << " improves on bit depth of " << total_bits
+              << "; making a palette image.\n";
+          }
 
 
           color_type = PNG_COLOR_TYPE_PALETTE;
           color_type = PNG_COLOR_TYPE_PALETTE;
 
 
@@ -611,36 +627,40 @@ write_data(xel *array, xelval *alpha_data) {
 
 
           png_set_PLTE(_png, _info, png_palette_table, palette.size());
           png_set_PLTE(_png, _info, png_palette_table, palette.size());
           if (has_alpha()) {
           if (has_alpha()) {
-            pnmimage_png_cat.debug()
-              << "palette contains " << num_alpha << " transparent entries.\n";
+            if (pnmimage_png_cat.is_debug()) {
+              pnmimage_png_cat.debug()
+                << "palette contains " << num_alpha << " transparent entries.\n";
+            }
             png_set_tRNS(_png, _info, png_trans, num_alpha, nullptr);
             png_set_tRNS(_png, _info, png_trans, num_alpha, nullptr);
           }
           }
-        } else {
+        } else if (pnmimage_png_cat.is_debug()) {
           pnmimage_png_cat.debug()
           pnmimage_png_cat.debug()
             << "palette bit depth of " << palette_bit_depth
             << "palette bit depth of " << palette_bit_depth
             << " does not improve on bit depth of " << total_bits
             << " does not improve on bit depth of " << total_bits
             << "; not making a palette image.\n";
             << "; not making a palette image.\n";
         }
         }
 
 
-      } else {
+      } else if (pnmimage_png_cat.is_debug()) {
         pnmimage_png_cat.debug()
         pnmimage_png_cat.debug()
           << "more than " << png_max_palette
           << "more than " << png_max_palette
           << " colors found; not making a palette image.\n";
           << " colors found; not making a palette image.\n";
       }
       }
-    } else {
+    } else if (pnmimage_png_cat.is_debug()) {
       pnmimage_png_cat.debug()
       pnmimage_png_cat.debug()
         << "maxval exceeds 255; not making a palette image.\n";
         << "maxval exceeds 255; not making a palette image.\n";
     }
     }
-  } else {
+  } else if (pnmimage_png_cat.is_debug()) {
     pnmimage_png_cat.debug()
     pnmimage_png_cat.debug()
       << "palette images are not enabled.\n";
       << "palette images are not enabled.\n";
   }
   }
 
 
-  pnmimage_png_cat.debug()
-    << "width = " << _x_size << " height = " << _y_size
-    << " maxval = " << _maxval << " bit_depth = "
-    << png_bit_depth << " color_type = " << color_type
-    << " color_space = " << _color_space << "\n";
+  if (pnmimage_png_cat.is_debug()) {
+    pnmimage_png_cat.debug()
+      << "width = " << _x_size << " height = " << _y_size
+      << " maxval = " << _maxval << " bit_depth = "
+      << png_bit_depth << " color_type = " << color_type
+      << " color_space = " << _color_space << "\n";
+  }
 
 
   png_set_IHDR(_png, _info, _x_size, _y_size, png_bit_depth,
   png_set_IHDR(_png, _info, _x_size, _y_size, png_bit_depth,
                color_type, PNG_INTERLACE_NONE,
                color_type, PNG_INTERLACE_NONE,

+ 21 - 0
tests/display/cg_bad.sha

@@ -0,0 +1,21 @@
+//Cg
+//
+
+void vshader(float4 vtx_position : POSITION,
+             float2 vtx_texcoord0 : TEXCOORD0,
+             uniform float4x4 mat_modelproj,
+             out float4 l_position : POSITION,
+             out float2 l_texcoord0 : TEXCOORD0)
+{
+  l_position = mul(mat_modelproj, vtx_position);
+  l_texcoord0 = vtx_texcoord0;
+}
+
+void fshader(float2 l_texcoord0 : TEXCOORD0,
+             uniform sampler2D tex_0 : TEXUNIT0,
+             out float4 o_color : COLOR)
+{
+  float4 texColor = tex2D(tex_0, l_texcoord0);
+  does_not_exist = texColor * 2 * (texColor.w - 0.5);
+}
+

+ 21 - 0
tests/display/cg_simple.sha

@@ -0,0 +1,21 @@
+//Cg
+//
+
+void vshader(float4 vtx_position : POSITION,
+             float2 vtx_texcoord0 : TEXCOORD0,
+             uniform float4x4 mat_modelproj,
+             out float4 l_position : POSITION,
+             out float2 l_texcoord0 : TEXCOORD0)
+{
+  l_position = mul(mat_modelproj, vtx_position);
+  l_texcoord0 = vtx_texcoord0;
+}
+
+void fshader(float2 l_texcoord0 : TEXCOORD0,
+             uniform sampler2D tex_0 : TEXUNIT0,
+             out float4 o_color : COLOR)
+{
+  float4 texColor = tex2D(tex_0, l_texcoord0);
+  o_color = texColor * 2 * (texColor.w - 0.5);
+}
+

+ 12 - 0
tests/display/glsl_bad.vert

@@ -0,0 +1,12 @@
+#version 130
+
+// Uniform inputs
+uniform mat4 p3d_ModelViewProjectionMatrix;
+
+// Vertex inputs
+in vec4 p3d_Vertex;
+
+void main() {
+  gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
+  does_not_exist = p3d_Vertex;
+}

+ 7 - 0
tests/display/glsl_include.vert

@@ -0,0 +1,7 @@
+#version 130
+
+#pragma include "glsl_include_inputs.vert"
+
+void main() {
+  gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
+}

+ 5 - 0
tests/display/glsl_include_inputs.vert

@@ -0,0 +1,5 @@
+// Uniform inputs
+uniform mat4 p3d_ModelViewProjectionMatrix;
+
+// Vertex inputs
+in vec4 p3d_Vertex;

+ 5 - 0
tests/display/glsl_simple.frag

@@ -0,0 +1,5 @@
+#version 130
+
+void main() {
+  gl_FragColor = vec4(0, 0, 0, 1);
+}

+ 11 - 0
tests/display/glsl_simple.vert

@@ -0,0 +1,11 @@
+#version 130
+
+// Uniform inputs
+uniform mat4 p3d_ModelViewProjectionMatrix;
+
+// Vertex inputs
+in vec4 p3d_Vertex;
+
+void main() {
+  gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
+}

+ 28 - 0
tests/display/test_cg_shader.py

@@ -0,0 +1,28 @@
+import os
+
+from panda3d import core
+
+
+SHADERS_DIR = core.Filename.from_os_specific(os.path.dirname(__file__))
+
+
+def run_cg_compile_check(gsg, shader_path, expect_fail=False):
+    """Compile supplied Cg shader path and check for errors"""
+    shader = core.Shader.load(shader_path, core.Shader.SL_Cg)
+    # assert shader.is_prepared(gsg.prepared_objects)
+    if expect_fail:
+        assert shader is None
+    else:
+        assert shader is not None
+
+
+def test_cg_compile_error(gsg):
+    """Test getting compile errors from bad Cg shaders"""
+    shader_path = core.Filename(SHADERS_DIR, 'cg_bad.sha')
+    run_cg_compile_check(gsg, shader_path, expect_fail=True)
+
+
+def test_cg_from_file(gsg):
+    """Test compiling Cg shaders from files"""
+    shader_path = core.Filename(SHADERS_DIR, 'cg_simple.sha')
+    run_cg_compile_check(gsg, shader_path)

+ 38 - 0
tests/display/test_glsl_shader.py

@@ -1,9 +1,13 @@
 from panda3d import core
 from panda3d import core
+import os
 import struct
 import struct
 import pytest
 import pytest
 from _pytest.outcomes import Failed
 from _pytest.outcomes import Failed
 
 
 
 
+SHADERS_DIR = core.Filename.from_os_specific(os.path.dirname(__file__))
+
+
 # This is the template for the compute shader that is used by run_glsl_test.
 # This is the template for the compute shader that is used by run_glsl_test.
 # It defines an assert() macro that writes failures to a buffer, indexed by
 # It defines an assert() macro that writes failures to a buffer, indexed by
 # line number.
 # line number.
@@ -102,6 +106,19 @@ def run_glsl_test(gsg, body, preamble="", inputs={}, version=150, exts=set()):
         pytest.fail("{0} GLSL assertions triggered:\n{1}".format(count, formatted))
         pytest.fail("{0} GLSL assertions triggered:\n{1}".format(count, formatted))
 
 
 
 
+def run_glsl_compile_check(gsg, vert_path, frag_path, expect_fail=False):
+    """Compile supplied GLSL shader paths and check for errors"""
+    shader = core.Shader.load(core.Shader.SL_GLSL, vert_path, frag_path)
+    assert shader is not None
+
+    shader.prepare_now(gsg.prepared_objects, gsg)
+    assert shader.is_prepared(gsg.prepared_objects)
+    if expect_fail:
+        assert shader.get_error_flag()
+    else:
+        assert not shader.get_error_flag()
+
+
 def test_glsl_test(gsg):
 def test_glsl_test(gsg):
     "Test to make sure that the GLSL tests work correctly."
     "Test to make sure that the GLSL tests work correctly."
 
 
@@ -359,3 +376,24 @@ def test_glsl_write_extract_image_buffer(gsg):
 
 
     assert struct.unpack('I', tex1.get_ram_image()) == (123,)
     assert struct.unpack('I', tex1.get_ram_image()) == (123,)
     assert struct.unpack('i', tex2.get_ram_image()) == (-456,)
     assert struct.unpack('i', tex2.get_ram_image()) == (-456,)
+
+
+def test_glsl_compile_error(gsg):
+    """Test getting compile errors from bad shaders"""
+    vert_path = core.Filename(SHADERS_DIR, 'glsl_bad.vert')
+    frag_path = core.Filename(SHADERS_DIR, 'glsl_simple.frag')
+    run_glsl_compile_check(gsg, vert_path, frag_path, expect_fail=True)
+
+
+def test_glsl_from_file(gsg):
+    """Test compiling GLSL shaders from files"""
+    vert_path = core.Filename(SHADERS_DIR, 'glsl_simple.vert')
+    frag_path = core.Filename(SHADERS_DIR, 'glsl_simple.frag')
+    run_glsl_compile_check(gsg, vert_path, frag_path)
+
+
+def test_glsl_includes(gsg):
+    """Test preprocessing includes in GLSL shaders"""
+    vert_path = core.Filename(SHADERS_DIR, 'glsl_include.vert')
+    frag_path = core.Filename(SHADERS_DIR, 'glsl_simple.frag')
+    run_glsl_compile_check(gsg, vert_path, frag_path)