Browse Source

Merge branch 'release/1.10.x'

rdb 4 years ago
parent
commit
842452594d

+ 1 - 1
direct/src/directtools/DirectManipulation.py

@@ -1068,7 +1068,7 @@ class ObjectHandles(NodePath, DirectObject):
         # Load up object handles model and assign it to self
         self.assign(base.loader.loadModel('models/misc/objectHandles'))
         self.setName(name)
-        self.scalingNode = self.getChild(0)
+        self.scalingNode = NodePath(self)
         self.scalingNode.setName('ohScalingNode')
         self.ohScalingFactor = 1.0
         self.directScalingFactor = 1.0

+ 4 - 0
panda/src/egldisplay/config_egldisplay.cxx

@@ -12,7 +12,9 @@
  */
 
 #include "config_egldisplay.h"
+#include "eglGraphicsBuffer.h"
 #include "eglGraphicsPipe.h"
+#include "eglGraphicsPixmap.h"
 #include "eglGraphicsWindow.h"
 #include "eglGraphicsStateGuardian.h"
 #include "graphicsPipeSelection.h"
@@ -44,8 +46,10 @@ init_libegldisplay() {
   }
   initialized = true;
 
+  eglGraphicsBuffer::init_type();
   eglGraphicsPipe::init_type();
 #ifdef HAVE_X11
+  eglGraphicsPixmap::init_type();
   eglGraphicsWindow::init_type();
 #endif
   eglGraphicsStateGuardian::init_type();

+ 24 - 0
panda/src/gles2gsg/gles2gsg.h

@@ -156,6 +156,18 @@ typedef char GLchar;
 #define GL_TEXTURE_MAX_LEVEL 0x813D
 #define GL_NUM_EXTENSIONS 0x821D
 #define GL_RG_INTEGER 0x8228
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
 #define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
 #define GL_PROGRAM_BINARY_LENGTH 0x8741
 #define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
@@ -196,6 +208,18 @@ typedef char GLchar;
 #define GL_SRGB8 0x8C41
 #define GL_SRGB8_ALPHA8 0x8C43
 #define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
 #define GL_RED_INTEGER 0x8D94
 #define GL_RGB_INTEGER 0x8D98
 #define GL_RGBA_INTEGER 0x8D99

+ 173 - 49
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -9531,6 +9531,8 @@ get_external_image_format(Texture *tex) const {
       case Texture::F_rgba16:
       case Texture::F_rgba32:
       case Texture::F_rgba8i:
+      case Texture::F_rgba16i:
+      case Texture::F_rgba32i:
       case Texture::F_rgb10_a2:
         return GL_COMPRESSED_RGBA;
 
@@ -9542,7 +9544,9 @@ get_external_image_format(Texture *tex) const {
       case Texture::F_rgb12:
       case Texture::F_rgb332:
       case Texture::F_rgb16:
+      case Texture::F_rgb16i:
       case Texture::F_rgb32:
+      case Texture::F_rgb32i:
         return GL_COMPRESSED_RGB;
 
       case Texture::F_alpha:
@@ -9561,7 +9565,9 @@ get_external_image_format(Texture *tex) const {
       case Texture::F_rg:
       case Texture::F_rg8i:
       case Texture::F_rg16:
+      case Texture::F_rg16i:
       case Texture::F_rg32:
+      case Texture::F_rg32i:
         return GL_COMPRESSED_RG;
 
       case Texture::F_luminance:
@@ -9816,10 +9822,16 @@ get_external_image_format(Texture *tex) const {
   case Texture::F_r32i:
     return GL_RED_INTEGER;
   case Texture::F_rg8i:
+  case Texture::F_rg16i:
+  case Texture::F_rg32i:
     return GL_RG_INTEGER;
   case Texture::F_rgb8i:
+  case Texture::F_rgb16i:
+  case Texture::F_rgb32i:
     return GL_RGB_INTEGER;
   case Texture::F_rgba8i:
+  case Texture::F_rgba16i:
+  case Texture::F_rgba32i:
     return GL_RGBA_INTEGER;
 #endif
 
@@ -9847,8 +9859,10 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
     // no compression for render targets
     compression = Texture::CM_off;
   }
-  bool is_3d = (tex->get_texture_type() == Texture::TT_3d_texture ||
-                tex->get_texture_type() == Texture::TT_2d_texture_array);
+  Texture::ComponentType component_type = tex->get_component_type();
+  Texture::TextureType texture_type = tex->get_texture_type();
+  bool is_3d = (texture_type == Texture::TT_3d_texture ||
+                texture_type == Texture::TT_2d_texture_array);
 
   if (get_supports_compressed_texture_format(compression)) {
     switch (compression) {
@@ -9871,7 +9885,13 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
       case Texture::F_rgb8i:
       case Texture::F_rgba8i:
       case Texture::F_r16i:
+      case Texture::F_rg16i:
+      case Texture::F_rgb16i:
+      case Texture::F_rgba16i:
       case Texture::F_r32i:
+      case Texture::F_rg32i:
+      case Texture::F_rgb32i:
+      case Texture::F_rgba32i:
       case Texture::F_r11_g11_b10:
       case Texture::F_rgb9_e5:
         // Unsupported; fall through to below.
@@ -9982,7 +10002,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
         }
 #endif
         if (get_supports_compressed_texture_format(Texture::CM_eac) && !is_3d) {
-          if (Texture::is_unsigned(tex->get_component_type())) {
+          if (Texture::is_unsigned(component_type)) {
             return GL_COMPRESSED_R11_EAC;
           } else {
             return GL_COMPRESSED_SIGNED_R11_EAC;
@@ -10008,7 +10028,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
         }
 #endif
         if (get_supports_compressed_texture_format(Texture::CM_eac) && !is_3d) {
-          if (Texture::is_unsigned(tex->get_component_type())) {
+          if (Texture::is_unsigned(component_type)) {
             return GL_COMPRESSED_RG11_EAC;
           } else {
             return GL_COMPRESSED_SIGNED_RG11_EAC;
@@ -10186,7 +10206,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
       break;
 
     case Texture::CM_eac:
-      if (Texture::is_unsigned(tex->get_component_type())) {
+      if (Texture::is_unsigned(component_type)) {
         if (tex->get_num_components() == 1) {
           return GL_COMPRESSED_R11_EAC;
         } else {
@@ -10219,7 +10239,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
   case Texture::F_depth_stencil:
     if (_supports_depth_stencil) {
 #ifndef OPENGLES
-      if (tex->get_component_type() == Texture::T_float) {
+      if (component_type == Texture::T_float) {
         return GL_DEPTH32F_STENCIL8;
       } else
 #endif
@@ -10231,7 +10251,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
 
   case Texture::F_depth_component:
 #ifndef OPENGLES
-    if (tex->get_component_type() == Texture::T_float) {
+    if (component_type == Texture::T_float) {
       return GL_DEPTH_COMPONENT32F;
     } else
 #endif
@@ -10266,7 +10286,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
       return GL_DEPTH_COMPONENT16_OES;
     }
 #else
-    if (tex->get_component_type() == Texture::T_float) {
+    if (component_type == Texture::T_float) {
       return GL_DEPTH_COMPONENT32F;
     } else {
       return GL_DEPTH_COMPONENT32;
@@ -10276,7 +10296,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
   case Texture::F_rgba:
   case Texture::F_rgbm:
 #ifndef OPENGLES_1
-    if (tex->get_component_type() == Texture::T_float) {
+    if (component_type == Texture::T_float) {
       return GL_RGBA16F;
     } else
 #endif
@@ -10286,11 +10306,11 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
       return _supports_bgr ? GL_BGRA : GL_RGBA;
     }
 #else
-    if (tex->get_component_type() == Texture::T_unsigned_short) {
+    if (component_type == Texture::T_unsigned_short) {
       return GL_RGBA16;
-    } else if (tex->get_component_type() == Texture::T_short) {
+    } else if (component_type == Texture::T_short) {
       return GL_RGBA16_SNORM;
-    } else if (tex->get_component_type() == Texture::T_byte) {
+    } else if (component_type == Texture::T_byte) {
       return GL_RGBA8_SNORM;
     } else {
       return force_sized ? GL_RGBA8 : GL_RGBA;
@@ -10307,32 +10327,32 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
     return _supports_bgr ? GL_BGRA : (force_sized ? GL_RGBA8 : GL_RGBA);
 #else
   case Texture::F_rgba8:
-    if (Texture::is_unsigned(tex->get_component_type())) {
+    if (Texture::is_unsigned(component_type)) {
       return GL_RGBA8;
     } else {
       return GL_RGBA8_SNORM;
     }
 
   case Texture::F_r8i:
-    if (Texture::is_unsigned(tex->get_component_type())) {
+    if (Texture::is_unsigned(component_type)) {
       return GL_R8UI;
     } else {
       return GL_R8I;
     }
   case Texture::F_rg8i:
-    if (Texture::is_unsigned(tex->get_component_type())) {
+    if (Texture::is_unsigned(component_type)) {
       return GL_RG8UI;
     } else {
       return GL_RG8I;
     }
   case Texture::F_rgb8i:
-    if (Texture::is_unsigned(tex->get_component_type())) {
+    if (Texture::is_unsigned(component_type)) {
       return GL_RGB8UI;
     } else {
       return GL_RGB8I;
     }
   case Texture::F_rgba8i:
-    if (Texture::is_unsigned(tex->get_component_type())) {
+    if (Texture::is_unsigned(component_type)) {
       return GL_RGBA8UI;
     } else {
       return GL_RGBA8I;
@@ -10342,9 +10362,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
 #endif  // OPENGLES
 #ifndef OPENGLES
   case Texture::F_rgba16:
-    if (tex->get_component_type() == Texture::T_float) {
+    if (component_type == Texture::T_float) {
       return GL_RGBA16F;
-    } else if (Texture::is_unsigned(tex->get_component_type())) {
+    } else if (Texture::is_unsigned(component_type)) {
       return GL_RGBA16;
     } else {
       return GL_RGBA16_SNORM;
@@ -10354,7 +10374,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
 #endif  // OPENGLES
 
   case Texture::F_rgb:
-    switch (tex->get_component_type()) {
+    switch (component_type) {
     case Texture::T_float: return GL_RGB16F;
 #ifndef OPENGLES
     case Texture::T_unsigned_short: return GL_RGB16;
@@ -10384,7 +10404,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
     return GL_RGB16F;
 #else
   case Texture::F_rgb8:
-    if (Texture::is_unsigned(tex->get_component_type())) {
+    if (Texture::is_unsigned(component_type)) {
       return GL_RGB8;
     } else {
       return GL_RGB8_SNORM;
@@ -10392,9 +10412,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
   case Texture::F_rgb12:
     return GL_RGB12;
   case Texture::F_rgb16:
-    if (tex->get_component_type() == Texture::T_float) {
+    if (component_type == Texture::T_float) {
       return GL_RGB16F;
-    } else if (Texture::is_unsigned(tex->get_component_type())) {
+    } else if (Texture::is_unsigned(component_type)) {
       return GL_RGB16;
     } else {
       return GL_RGB16_SNORM;
@@ -10415,26 +10435,44 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
     return GL_RG16F_EXT;
 #elif !defined(OPENGLES_1)
   case Texture::F_r16:
-    if (tex->get_component_type() == Texture::T_float) {
+    if (component_type == Texture::T_float) {
       return GL_R16F;
-    } else if (Texture::is_unsigned(tex->get_component_type())) {
+    } else if (Texture::is_unsigned(component_type)) {
       return GL_R16;
     } else {
       return GL_R16_SNORM;
     }
+  case Texture::F_rg16:
+    if (component_type == Texture::T_float) {
+      return GL_RG16F;
+    } else if (Texture::is_unsigned(component_type)) {
+      return GL_RG16;
+    } else {
+      return GL_RG16_SNORM;
+    }
   case Texture::F_r16i:
-    if (Texture::is_unsigned(tex->get_component_type())) {
+    if (Texture::is_unsigned(component_type)) {
       return GL_R16UI;
     } else {
       return GL_R16I;
     }
-  case Texture::F_rg16:
-    if (tex->get_component_type() == Texture::T_float) {
-      return GL_RG16F;
-    } else if (Texture::is_unsigned(tex->get_component_type())) {
-      return GL_RG16;
+  case Texture::F_rg16i:
+    if (Texture::is_unsigned(component_type)) {
+      return GL_RG16UI;
     } else {
-      return GL_RG16_SNORM;
+      return GL_RG16I;
+    }
+  case Texture::F_rgb16i:
+    if (Texture::is_unsigned(component_type)) {
+      return GL_RGB16UI;
+    } else {
+      return GL_RGB16I;
+    }
+  case Texture::F_rgba16i:
+    if (Texture::is_unsigned(component_type)) {
+      return GL_RGBA16UI;
+    } else {
+      return GL_RGBA16I;
     }
 #endif
 
@@ -10448,7 +10486,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
   case Texture::F_green:
   case Texture::F_blue:
 #ifndef OPENGLES
-    if (!Texture::is_unsigned(tex->get_component_type())) {
+    if (!Texture::is_unsigned(component_type)) {
       return GL_R8_SNORM;
     } else
 #endif
@@ -10473,7 +10511,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
     return force_sized ? GL_LUMINANCE8 : GL_LUMINANCE;
 #else
     if (_supports_luminance_texture) {
-      switch (tex->get_component_type()) {
+      switch (component_type) {
       case Texture::T_float:
       case Texture::T_half_float:
         return GL_LUMINANCE16F_ARB;
@@ -10485,7 +10523,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
         return force_sized ? GL_LUMINANCE8 : GL_LUMINANCE;
       }
     } else {
-      switch (tex->get_component_type()) {
+      switch (component_type) {
       case Texture::T_float:
       case Texture::T_half_float:
         return GL_R16F;
@@ -10504,7 +10542,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
     return force_sized ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA;
 #else
     if (_supports_luminance_texture) {
-      switch (tex->get_component_type()) {
+      switch (component_type) {
       case Texture::T_float:
       case Texture::T_half_float:
         return GL_LUMINANCE_ALPHA16F_ARB;
@@ -10516,7 +10554,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
         return force_sized ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA;
       }
     } else {
-      switch (tex->get_component_type()) {
+      switch (component_type) {
       case Texture::T_float:
       case Texture::T_half_float:
         return GL_RG16F;
@@ -10548,9 +10586,31 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
     return _core_profile ? GL_SRGB8_ALPHA8 : GL_SLUMINANCE8_ALPHA8;
 #endif
 
-#ifndef OPENGLES
+#ifndef OPENGLES_1
   case Texture::F_r32i:
-    return GL_R32I;
+    if (Texture::is_unsigned(component_type)) {
+      return GL_R32UI;
+    } else {
+      return GL_R32I;
+    }
+  case Texture::F_rg32i:
+    if (Texture::is_unsigned(component_type)) {
+      return GL_RG32UI;
+    } else {
+      return GL_RG32I;
+    }
+  case Texture::F_rgb32i:
+    if (Texture::is_unsigned(component_type)) {
+      return GL_RGB32UI;
+    } else {
+      return GL_RGB32I;
+    }
+  case Texture::F_rgba32i:
+    if (Texture::is_unsigned(component_type)) {
+      return GL_RGBA32UI;
+    } else {
+      return GL_RGBA32I;
+    }
 #endif
 
 #ifndef OPENGLES_1
@@ -12632,10 +12692,20 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) {
     }
   }
 
-  glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
-                  get_texture_filter_type(minfilter, !uses_mipmaps));
-  glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
-                  get_texture_filter_type(magfilter, true));
+  if (Texture::is_integer(tex->get_format())) {
+    // Integer format textures can't have filtering enabled, and in fact, some
+    // drivers (looking at you, Intel) will always sample (0, 0, 0, 1) if we
+    // don't set this correctly!
+    glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
+                    uses_mipmaps ? GL_NEAREST_MIPMAP_NEAREST
+                                 : GL_NEAREST);
+    glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  } else {
+    glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
+                    get_texture_filter_type(minfilter, !uses_mipmaps));
+    glTexParameteri(target, GL_TEXTURE_MAG_FILTER,
+                    get_texture_filter_type(magfilter, true));
+  }
 
   // Set anisotropic filtering.
   if (_supports_anisotropy) {
@@ -14185,7 +14255,9 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
   case GL_R3_G3_B2:
     format = Texture::F_rgb332;
     break;
+#endif
 
+#ifndef OPENGLES_1
   case GL_R8I:
     type = Texture::T_byte;
     format = Texture::F_r8i;
@@ -14224,11 +14296,69 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     type = Texture::T_short;
     format = Texture::F_r16i;
     break;
+  case GL_RG16I:
+    type = Texture::T_short;
+    format = Texture::F_rg16i;
+    break;
+  case GL_RGB16I:
+    type = Texture::T_short;
+    format = Texture::F_rgb16i;
+    break;
+  case GL_RGBA16I:
+    type = Texture::T_short;
+    format = Texture::F_rgba16i;
+    break;
+
   case GL_R16UI:
     type = Texture::T_unsigned_short;
     format = Texture::F_r16i;
     break;
+  case GL_RG16UI:
+    type = Texture::T_unsigned_short;
+    format = Texture::F_rg16i;
+    break;
+  case GL_RGB16UI:
+    type = Texture::T_unsigned_short;
+    format = Texture::F_rgb16i;
+    break;
+  case GL_RGBA16UI:
+    type = Texture::T_unsigned_short;
+    format = Texture::F_rgba16i;
+    break;
 
+  case GL_R32I:
+    type = Texture::T_int;
+    format = Texture::F_r32i;
+    break;
+  case GL_RG32I:
+    type = Texture::T_int;
+    format = Texture::F_rg32i;
+    break;
+  case GL_RGB32I:
+    type = Texture::T_int;
+    format = Texture::F_rgb32i;
+    break;
+  case GL_RGBA32I:
+    type = Texture::T_int;
+    format = Texture::F_rgba32i;
+    break;
+
+  case GL_R32UI:
+    type = Texture::T_unsigned_int;
+    format = Texture::F_r32i;
+    break;
+  case GL_RG32UI:
+    type = Texture::T_unsigned_int;
+    format = Texture::F_rg32i;
+    break;
+  case GL_RGB32UI:
+    type = Texture::T_unsigned_int;
+    format = Texture::F_rgb32i;
+    break;
+  case GL_RGBA32UI:
+    type = Texture::T_unsigned_int;
+    format = Texture::F_rgba32i;
+    break;
 #endif
 
 #ifndef OPENGLES_1
@@ -14317,12 +14447,6 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     format = Texture::F_red;
     break;
 #endif
-#ifndef OPENGLES
-  case GL_R32I:
-    type = Texture::T_int;
-    format = Texture::F_r32i;
-    break;
-#endif
 
 #ifndef OPENGLES
   case GL_RED:

+ 5 - 0
panda/src/glstuff/glShaderContext_src.cxx

@@ -2808,6 +2808,11 @@ update_shader_texture_bindings(ShaderContext *prev) {
       }
       continue;
     }
+    else if (Texture::is_integer(tex->get_format())) {
+      // Required to satisfy Intel drivers, which will otherwise sample zero.
+      sampler.set_minfilter(sampler.uses_mipmaps() ? SamplerState::FT_nearest_mipmap_nearest : SamplerState::FT_nearest);
+      sampler.set_magfilter(SamplerState::FT_nearest);
+    }
 
     if (tex->get_texture_type() != spec._desired_type) {
       switch (spec._part) {

+ 145 - 12
panda/src/gobj/texture.cxx

@@ -676,7 +676,7 @@ estimate_texture_memory() const {
   CDReader cdata(_cycler);
   size_t pixels = cdata->_x_size * cdata->_y_size * cdata->_z_size;
 
-  size_t bpp = 4;
+  size_t bpp = 0;
   switch (cdata->_format) {
   case Texture::F_rgb332:
     bpp = 1;
@@ -739,10 +739,8 @@ estimate_texture_memory() const {
     bpp = 8;
     break;
 
-  case Texture::F_rgba16:
-    bpp = 8;
-    break;
   case Texture::F_rgba32:
+  case Texture::F_rgba32i:
     bpp = 16;
     break;
 
@@ -752,9 +750,13 @@ estimate_texture_memory() const {
     bpp = 2;
     break;
   case Texture::F_rg16:
+  case Texture::F_rg16i:
     bpp = 4;
     break;
   case Texture::F_rgb16:
+  case Texture::F_rgb16i:
+  case Texture::F_rgba16:
+  case Texture::F_rgba16i:
     bpp = 8;
     break;
 
@@ -764,10 +766,12 @@ estimate_texture_memory() const {
     break;
 
   case Texture::F_rg32:
+  case Texture::F_rg32i:
     bpp = 8;
     break;
 
   case Texture::F_rgb32:
+  case Texture::F_rgb32i:
     bpp = 16;
     break;
 
@@ -776,11 +780,12 @@ estimate_texture_memory() const {
   case Texture::F_rgb10_a2:
     bpp = 4;
     break;
+  }
 
-  default:
+  if (bpp == 0) {
+    bpp = 4;
     gobj_cat.warning() << "Unhandled format in estimate_texture_memory(): "
                        << cdata->_format << "\n";
-    break;
   }
 
   size_t bytes = pixels * bpp;
@@ -1789,10 +1794,6 @@ write(ostream &out, int indent_level) const {
   case F_r16:
     out << "r16";
     break;
-  case F_r16i:
-    out << "r16i";
-    break;
-
   case F_rg16:
     out << "rg16";
     break;
@@ -1852,6 +1853,29 @@ write(ostream &out, int indent_level) const {
   case F_rg:
     out << "rg";
     break;
+
+  case F_r16i:
+    out << "r16i";
+    break;
+  case F_rg16i:
+    out << "rg16i";
+    break;
+  case F_rgb16i:
+    out << "rgb16i";
+    break;
+  case F_rgba16i:
+    out << "rgba16i";
+    break;
+
+  case F_rg32i:
+    out << "rg32i";
+    break;
+  case F_rgb32i:
+    out << "rgb32i";
+    break;
+  case F_rgba32i:
+    out << "rgba32i";
+    break;
   }
 
   if (cdata->_compression != CM_default) {
@@ -2217,8 +2241,6 @@ format_format(Format format) {
     return "rgba32";
   case F_r16:
     return "r16";
-  case F_r16i:
-    return "r16i";
   case F_rg16:
     return "rg16";
   case F_rgb16:
@@ -2255,6 +2277,20 @@ format_format(Format format) {
     return "rgb10_a2";
   case F_rg:
     return "rg";
+  case F_r16i:
+    return "r16i";
+  case F_rg16i:
+    return "rg16i";
+  case F_rgb16i:
+    return "rgb16i";
+  case F_rgba16i:
+    return "rgba16i";
+  case F_rg32i:
+    return "rg32i";
+  case F_rgb32i:
+    return "rgb32i";
+  case F_rgba32i:
+    return "rgba32i";
   }
   return "**invalid**";
 }
@@ -2340,6 +2376,14 @@ string_format(const string &str) {
     return F_rg32;
   } else if (cmp_nocase(str, "rgb32") == 0 || cmp_nocase(str, "r32g32b32") == 0) {
     return F_rgb32;
+  } else if (cmp_nocase_uh(str, "r8i") == 0) {
+    return F_r8i;
+  } else if (cmp_nocase_uh(str, "rg8i") == 0 || cmp_nocase_uh(str, "r8g8i") == 0) {
+    return F_rg8i;
+  } else if (cmp_nocase_uh(str, "rgb8i") == 0 || cmp_nocase_uh(str, "r8g8b8i") == 0) {
+    return F_rgb8i;
+  } else if (cmp_nocase_uh(str, "rgba8i") == 0 || cmp_nocase_uh(str, "r8g8b8a8i") == 0) {
+    return F_rgba8i;
   } else if (cmp_nocase(str, "r11g11b10") == 0) {
     return F_r11_g11_b10;
   } else if (cmp_nocase(str, "rgb9_e5") == 0) {
@@ -2348,6 +2392,20 @@ string_format(const string &str) {
     return F_rgb10_a2;
   } else if (cmp_nocase_uh(str, "rg") == 0) {
     return F_rg;
+  } else if (cmp_nocase_uh(str, "r16i") == 0) {
+    return F_r16i;
+  } else if (cmp_nocase_uh(str, "rg16i") == 0 || cmp_nocase_uh(str, "r16g16i") == 0) {
+    return F_rg16i;
+  } else if (cmp_nocase_uh(str, "rgb16i") == 0 || cmp_nocase_uh(str, "r16g16b16i") == 0) {
+    return F_rgb16i;
+  } else if (cmp_nocase_uh(str, "rgba16i") == 0 || cmp_nocase_uh(str, "r16g16b16a16i") == 0) {
+    return F_rgba16i;
+  } else if (cmp_nocase_uh(str, "rg32i") == 0 || cmp_nocase_uh(str, "r32g32i") == 0) {
+    return F_rg32i;
+  } else if (cmp_nocase_uh(str, "rgb32i") == 0 || cmp_nocase_uh(str, "r32g32b32i") == 0) {
+    return F_rgb32i;
+  } else if (cmp_nocase_uh(str, "rgba32i") == 0 || cmp_nocase_uh(str, "r32g32b32a32i") == 0) {
+    return F_rgba32i;
   }
 
   gobj_cat->error()
@@ -2588,6 +2646,8 @@ has_alpha(Format format) {
   case F_sluminance_alpha:
   case F_rgba8i:
   case F_rgb10_a2:
+  case F_rgba16i:
+  case F_rgba32i:
     return true;
 
   default:
@@ -2628,6 +2688,31 @@ is_srgb(Format format) {
   }
 }
 
+/**
+ * Returns true if the indicated format is an integer format, false otherwise.
+ */
+bool Texture::
+is_integer(Format format) {
+  switch (format) {
+  case F_r32i:
+  case F_r8i:
+  case F_rg8i:
+  case F_rgb8i:
+  case F_rgba8i:
+  case F_r16i:
+  case F_rg16i:
+  case F_rgb16i:
+  case F_rgba16i:
+  case F_rg32i:
+  case F_rgb32i:
+  case F_rgba32i:
+    return true;
+
+  default:
+    return false;
+  }
+}
+
 /**
  * Computes the proper size of the texture, based on the original size, the
  * filename, and the resizing whims of the config file.
@@ -3674,11 +3759,31 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
       component_type = T_unsigned_short;
       func = read_dds_level_abgr16;
       break;
+    case 12:   // DXGI_FORMAT_R16G16B16A16_UINT
+      format = F_rgba16i;
+      component_type = T_unsigned_short;
+      func = read_dds_level_abgr16;
+      break;
+    case 14:   // DXGI_FORMAT_R16G16B16A16_SINT
+      format = F_rgba16i;
+      component_type = T_short;
+      func = read_dds_level_abgr16;
+      break;
     case 16:   // DXGI_FORMAT_R32G32_FLOAT
       format = F_rg32;
       component_type = T_float;
       func = read_dds_level_raw;
       break;
+    case 17:   // DXGI_FORMAT_R32G32_UINT
+      format = F_rg32i;
+      component_type = T_unsigned_int;
+      func = read_dds_level_raw;
+      break;
+    case 18:   // DXGI_FORMAT_R32G32_SINT
+      format = F_rg32i;
+      component_type = T_int;
+      func = read_dds_level_raw;
+      break;
     case 27:   // DXGI_FORMAT_R8G8B8A8_TYPELESS
     case 28:   // DXGI_FORMAT_R8G8B8A8_UNORM
       format = F_rgba8;
@@ -3712,11 +3817,21 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
       component_type = T_unsigned_short;
       func = read_dds_level_raw;
       break;
+    case 36:   // DXGI_FORMAT_R16G16_UINT:
+      format = F_rg16i;
+      component_type = T_unsigned_short;
+      func = read_dds_level_raw;
+      break;
     case 37:   // DXGI_FORMAT_R16G16_SNORM:
       format = F_rg16;
       component_type = T_short;
       func = read_dds_level_raw;
       break;
+    case 38:   // DXGI_FORMAT_R16G16_SINT:
+      format = F_rg16i;
+      component_type = T_short;
+      func = read_dds_level_raw;
+      break;
     case 40:   // DXGI_FORMAT_D32_FLOAT
       format = F_depth_component32;
       component_type = T_float;
@@ -4611,8 +4726,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only)
         break;
       case KTX_RG16I:
       case KTX_RG16UI:
+        format = F_rg16i;
+        break;
       case KTX_RG32I:
       case KTX_RG32UI:
+        format = F_rg32i;
+        break;
       default:
         gobj_cat.error()
           << filename << " has unsupported RG integer format " << internal_format << "\n";
@@ -4676,8 +4795,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only)
         break;
       case KTX_RGB16I:
       case KTX_RGB16UI:
+        format = F_rgb16i;
+        break;
       case KTX_RGB32I:
       case KTX_RGB32UI:
+        format = F_rgb32i;
+        break;
       default:
         gobj_cat.error()
           << filename << " has unsupported RGB integer format " << internal_format << "\n";
@@ -4739,8 +4862,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only)
         break;
       case KTX_RGBA16I:
       case KTX_RGBA16UI:
+        format = F_rgba16i;
+        break;
       case KTX_RGBA32I:
       case KTX_RGBA32UI:
+        format = F_rgba32i;
+        break;
       default:
         gobj_cat.error()
           << filename << " has unsupported RGBA integer format " << internal_format << "\n";
@@ -6877,6 +7004,8 @@ do_set_format(CData *cdata, Texture::Format format) {
   case F_rg32:
   case F_rg8i:
   case F_rg:
+  case F_rg16i:
+  case F_rg32i:
     cdata->_num_components = 2;
     break;
 
@@ -6891,6 +7020,8 @@ do_set_format(CData *cdata, Texture::Format format) {
   case F_rgb8i:
   case F_r11_g11_b10:
   case F_rgb9_e5:
+  case F_rgb16i:
+  case F_rgb32i:
     cdata->_num_components = 3;
     break;
 
@@ -6905,6 +7036,8 @@ do_set_format(CData *cdata, Texture::Format format) {
   case F_srgb_alpha:
   case F_rgba8i:
   case F_rgb10_a2:
+  case F_rgba16i:
+  case F_rgba32i:
     cdata->_num_components = 4;
     break;
   }

+ 10 - 1
panda/src/gobj/texture.h

@@ -161,7 +161,15 @@ PUBLISHED:
     F_rgb10_a2,
 
     F_rg,
-    F_r16i
+
+    F_r16i,
+    F_rg16i,
+    F_rgb16i, // not recommended
+    F_rgba16i,
+
+    F_rg32i,
+    F_rgb32i,
+    F_rgba32i,
   };
 
   // Deprecated.  See SamplerState.FilterType.
@@ -625,6 +633,7 @@ public:
   static bool has_alpha(Format format);
   static bool has_binary_alpha(Format format);
   static bool is_srgb(Format format);
+  static bool is_integer(Format format);
 
   static bool adjust_size(int &x_size, int &y_size, const std::string &name,
                           bool for_padding, AutoTextureScale auto_texture_scale = ATS_unspecified);

+ 120 - 24
panda/src/gobj/texturePeeker.cxx

@@ -14,6 +14,58 @@
 #include "texturePeeker.h"
 
 
+static double get_unsigned_byte_i(const unsigned char *&p) {
+  return *p++;
+}
+
+static double get_signed_byte_i(const unsigned char *&p) {
+  return *(signed char *)p++;
+}
+
+static double get_unsigned_short_i(const unsigned char *&p) {
+  union {
+    unsigned short us;
+    unsigned char uc[2];
+  } v;
+  v.uc[0] = (*p++);
+  v.uc[1] = (*p++);
+  return (double)v.us;
+}
+
+static double get_signed_short_i(const unsigned char *&p) {
+  union {
+    signed short ss;
+    unsigned char uc[2];
+  } v;
+  v.uc[0] = (*p++);
+  v.uc[1] = (*p++);
+  return (double)v.ss;
+}
+
+static double get_unsigned_int_i(const unsigned char *&p) {
+  union {
+    unsigned int ui;
+    unsigned char uc[4];
+  } v;
+  v.uc[0] = (*p++);
+  v.uc[1] = (*p++);
+  v.uc[2] = (*p++);
+  v.uc[3] = (*p++);
+  return (double)v.ui;
+}
+
+static double get_signed_int_i(const unsigned char *&p) {
+  union {
+    signed int si;
+    unsigned char uc[4];
+  } v;
+  v.uc[0] = (*p++);
+  v.uc[1] = (*p++);
+  v.uc[2] = (*p++);
+  v.uc[3] = (*p++);
+  return (double)v.si;
+}
+
 /**
  * Use Texture::peek() to construct a TexturePeeker.
  *
@@ -73,35 +125,69 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) {
   }
   _pixel_width = _component_width * _num_components;
 
-  switch (_component_type) {
-  case Texture::T_unsigned_byte:
-    _get_component = Texture::get_unsigned_byte;
-    break;
+  if (Texture::is_integer(_format)) {
+    switch (_component_type) {
+    case Texture::T_unsigned_byte:
+      _get_component = get_unsigned_byte_i;
+      break;
 
-  case Texture::T_unsigned_short:
-    _get_component = Texture::get_unsigned_short;
-    break;
+    case Texture::T_unsigned_short:
+      _get_component = get_unsigned_short_i;
+      break;
 
-  case Texture::T_unsigned_int:
-    _get_component = Texture::get_unsigned_int;
-    break;
+    case Texture::T_unsigned_int:
+      _get_component = get_unsigned_int_i;
+      break;
 
-  case Texture::T_float:
-    _get_component = Texture::get_float;
-    break;
+    case Texture::T_byte:
+      _get_component = get_signed_byte_i;
+      break;
 
-  case Texture::T_half_float:
-    _get_component = Texture::get_half_float;
-    break;
+    case Texture::T_short:
+      _get_component = get_signed_short_i;
+      break;
 
-  case Texture::T_unsigned_int_24_8:
-    _get_component = Texture::get_unsigned_int_24;
-    break;
+    case Texture::T_int:
+      _get_component = get_signed_int_i;
+      break;
 
-  default:
-    // Not supported.
-    _image.clear();
-    return;
+    default:
+      // Not supported.
+      _image.clear();
+      return;
+    }
+  }
+  else {
+    switch (_component_type) {
+    case Texture::T_unsigned_byte:
+      _get_component = Texture::get_unsigned_byte;
+      break;
+
+    case Texture::T_unsigned_short:
+      _get_component = Texture::get_unsigned_short;
+      break;
+
+    case Texture::T_unsigned_int:
+      _get_component = Texture::get_unsigned_int;
+      break;
+
+    case Texture::T_float:
+      _get_component = Texture::get_float;
+      break;
+
+    case Texture::T_half_float:
+      _get_component = Texture::get_half_float;
+      break;
+
+    case Texture::T_unsigned_int_24_8:
+      _get_component = Texture::get_unsigned_int_24;
+      break;
+
+    default:
+      // Not supported.
+      _image.clear();
+      return;
+    }
   }
 
   switch (_format) {
@@ -114,6 +200,7 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) {
   case Texture::F_r16:
   case Texture::F_r32:
   case Texture::F_r32i:
+  case Texture::F_r16i:
     _get_texel = get_texel_r;
     break;
 
@@ -140,21 +227,27 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) {
     _get_texel = get_texel_la;
     break;
 
+  case Texture::F_rg:
+  case Texture::F_rg8i:
   case Texture::F_rg16:
+  case Texture::F_rg16i:
   case Texture::F_rg32:
-  case Texture::F_rg:
+  case Texture::F_rg32i:
     _get_texel = get_texel_rg;
     break;
 
   case Texture::F_rgb:
   case Texture::F_rgb5:
   case Texture::F_rgb8:
+  case Texture::F_rgb8i:
   case Texture::F_rgb12:
   case Texture::F_rgb16:
+  case Texture::F_rgb16i:
   case Texture::F_rgb332:
   case Texture::F_r11_g11_b10:
   case Texture::F_rgb9_e5:
   case Texture::F_rgb32:
+  case Texture::F_rgb32i:
     _get_texel = get_texel_rgb;
     break;
 
@@ -163,9 +256,12 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) {
   case Texture::F_rgba4:
   case Texture::F_rgba5:
   case Texture::F_rgba8:
+  case Texture::F_rgba8i:
   case Texture::F_rgba12:
   case Texture::F_rgba16:
+  case Texture::F_rgba16i:
   case Texture::F_rgba32:
+  case Texture::F_rgba32i:
   case Texture::F_rgb10_a2:
     _get_texel = get_texel_rgba;
     break;

+ 1 - 0
panda/src/grutil/multitexReducer.cxx

@@ -714,6 +714,7 @@ make_texture_layer(const NodePath &render,
   case TextureStage::M_height:
   case TextureStage::M_selector:
   case TextureStage::M_normal_gloss:
+  case TextureStage::M_emission:
     // Don't know what to do with these funny modes.  We should probably raise
     // an exception or something.  Fall through for now.
 

+ 1 - 1
panda/src/pgraph/shaderInput_ext.cxx

@@ -274,7 +274,7 @@ __init__(CPT_InternalName name, PyObject *value, int priority) {
       return;
     }
 
-    Py_ssize_t num_items = PySequence_Fast_GET_SIZE(value);
+    Py_ssize_t num_items = PySequence_Fast_GET_SIZE(fast);
     if (num_items <= 0) {
       // We can't determine the type of a list of size 0.
       _this->_type = ShaderInput::M_numeric;

+ 119 - 1
tests/display/test_glsl_shader.py

@@ -141,15 +141,77 @@ def test_glsl_sampler(gsg):
     tex2.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_rgba32)
     tex2.set_clear_color((1.0, 2.0, -3.14, 0.0))
 
+    tex3 = core.Texture("")
+    tex3.setup_3d_texture(1, 1, 1, core.Texture.T_float, core.Texture.F_r32)
+    tex3.set_clear_color((0.5, 0.0, 0.0, 1.0))
+
     preamble = """
     uniform sampler1D tex1;
     uniform sampler2D tex2;
+    uniform sampler3D tex3;
     """
     code = """
     assert(texelFetch(tex1, 0, 0) == vec4(0, 2 / 255.0, 1, 1));
     assert(texelFetch(tex2, ivec2(0, 0), 0) == vec4(1.0, 2.0, -3.14, 0.0));
+    assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == vec4(0.5, 0.0, 0.0, 1.0));
     """
-    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
+    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
+
+
+def test_glsl_isampler(gsg):
+    from struct import pack
+
+    tex1 = core.Texture("")
+    tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i)
+    tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3))
+
+    tex2 = core.Texture("")
+    tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i)
+    tex2.set_ram_image(pack('h', 4))
+
+    tex3 = core.Texture("")
+    tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i)
+    tex3.set_ram_image(pack('i', 5))
+
+    preamble = """
+    uniform isampler1D tex1;
+    uniform isampler2D tex2;
+    uniform isampler3D tex3;
+    """
+    code = """
+    assert(texelFetch(tex1, 0, 0) == ivec4(0, 1, 2, 3));
+    assert(texelFetch(tex2, ivec2(0, 0), 0) == ivec4(4, 0, 0, 1));
+    assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == ivec4(5, 0, 0, 1));
+    """
+    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
+
+
+def test_glsl_usampler(gsg):
+    from struct import pack
+
+    tex1 = core.Texture("")
+    tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i)
+    tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3))
+
+    tex2 = core.Texture("")
+    tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i)
+    tex2.set_ram_image(pack('H', 4))
+
+    tex3 = core.Texture("")
+    tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i)
+    tex3.set_ram_image(pack('I', 5))
+
+    preamble = """
+    uniform usampler1D tex1;
+    uniform usampler2D tex2;
+    uniform usampler3D tex3;
+    """
+    code = """
+    assert(texelFetch(tex1, 0, 0) == uvec4(0, 1, 2, 3));
+    assert(texelFetch(tex2, ivec2(0, 0), 0) == uvec4(4, 0, 0, 1));
+    assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == uvec4(5, 0, 0, 1));
+    """
+    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
 
 
 def test_glsl_image(gsg):
@@ -172,6 +234,62 @@ def test_glsl_image(gsg):
     run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
 
 
+def test_glsl_iimage(gsg):
+    from struct import pack
+
+    tex1 = core.Texture("")
+    tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i)
+    tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3))
+
+    tex2 = core.Texture("")
+    tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i)
+    tex2.set_ram_image(pack('h', 4))
+
+    tex3 = core.Texture("")
+    tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i)
+    tex3.set_ram_image(pack('i', 5))
+
+    preamble = """
+    layout(rgba8i) uniform iimage1D tex1;
+    layout(r16i) uniform iimage2D tex2;
+    layout(r32i) uniform iimage3D tex3;
+    """
+    code = """
+    assert(imageLoad(tex1, 0) == ivec4(0, 1, 2, 3));
+    assert(imageLoad(tex2, ivec2(0, 0)) == ivec4(4, 0, 0, 1));
+    assert(imageLoad(tex3, ivec3(0, 0, 0)) == ivec4(5, 0, 0, 1));
+    """
+    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
+
+
+def test_glsl_uimage(gsg):
+    from struct import pack
+
+    tex1 = core.Texture("")
+    tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i)
+    tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3))
+
+    tex2 = core.Texture("")
+    tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i)
+    tex2.set_ram_image(pack('H', 4))
+
+    tex3 = core.Texture("")
+    tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i)
+    tex3.set_ram_image(pack('I', 5))
+
+    preamble = """
+    layout(rgba8ui) uniform uimage1D tex1;
+    layout(r16ui) uniform uimage2D tex2;
+    layout(r32ui) uniform uimage3D tex3;
+    """
+    code = """
+    assert(imageLoad(tex1, 0) == uvec4(0, 1, 2, 3));
+    assert(imageLoad(tex2, ivec2(0, 0)) == uvec4(4, 0, 0, 1));
+    assert(imageLoad(tex3, ivec3(0, 0, 0)) == uvec4(5, 0, 0, 1));
+    """
+    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3})
+
+
 def test_glsl_ssbo(gsg):
     from struct import pack
     num1 = pack('<i', 1234567)

+ 64 - 0
tests/gobj/test_texture_peek.py

@@ -94,3 +94,67 @@ def test_texture_peek_srgba():
 
     # We allow some imprecision.
     assert col.almost_equal((0.5, 0.5, 0.5, 188 / 255.0), 1 / 255.0)
+
+
+def test_texture_peek_ubyte_i():
+    maxval = 255
+    data = array('B', (2, 1, 0, maxval))
+    peeker = peeker_from_pixel(Texture.T_unsigned_byte, Texture.F_rgba8i, data)
+
+    col = LColor()
+    peeker.fetch_pixel(col, 0, 0)
+    assert col == (0, 1, 2, maxval)
+
+
+def test_texture_peek_byte_i():
+    minval = -128
+    maxval = 127
+    data = array('b', (0, -1, minval, maxval))
+    peeker = peeker_from_pixel(Texture.T_byte, Texture.F_rgba8i, data)
+
+    col = LColor()
+    peeker.fetch_pixel(col, 0, 0)
+    assert col == (minval, -1, 0, maxval)
+
+
+def test_texture_peek_ushort_i():
+    maxval = 65535
+    data = array('H', (2, 1, 0, maxval))
+    peeker = peeker_from_pixel(Texture.T_unsigned_short, Texture.F_rgba16i, data)
+
+    col = LColor()
+    peeker.fetch_pixel(col, 0, 0)
+    assert col == (0, 1, 2, maxval)
+
+
+def test_texture_peek_short_i():
+    minval = -32768
+    maxval = 32767
+    data = array('h', (0, -1, minval, maxval))
+    peeker = peeker_from_pixel(Texture.T_short, Texture.F_rgba16i, data)
+
+    col = LColor()
+    peeker.fetch_pixel(col, 0, 0)
+    assert col == (minval, -1, 0, maxval)
+
+
+def test_texture_peek_uint_i():
+    # Highest integer that fits inside float
+    maxval = 2147483648
+    data = array('I', (2, 1, 0, maxval))
+    peeker = peeker_from_pixel(Texture.T_unsigned_int, Texture.F_rgba32i, data)
+
+    col = LColor()
+    peeker.fetch_pixel(col, 0, 0)
+    assert col == (0, 1, 2, maxval)
+
+
+def test_texture_peek_int_i():
+    minval = -2147483648
+    maxval = 2147483647
+    data = array('i', (0, -1, minval, maxval))
+    peeker = peeker_from_pixel(Texture.T_int, Texture.F_rgba32i, data)
+
+    col = LColor()
+    peeker.fetch_pixel(col, 0, 0)
+    assert col == (minval, -1, 0, maxval)

+ 5 - 0
tests/pgraph/test_shaderinput.py

@@ -1,4 +1,9 @@
 from panda3d.core import ShaderInput, Vec4
+from array import array
+
+
+def test_shaderinput_construct_sequence_int():
+    i = ShaderInput('test', array('I', [1, 2, 3, 4]))
 
 
 def test_shaderinput_vector_compare():