Bläddra i källkod

Fix DDS load crash with certain formats; support R16, RG16, R32, RG32

rdb 9 år sedan
förälder
incheckning
23645cc407
2 ändrade filer med 96 tillägg och 4 borttagningar
  1. 94 4
      panda/src/gobj/texture.cxx
  2. 2 0
      panda/src/gobj/texture.h

+ 94 - 4
panda/src/gobj/texture.cxx

@@ -3643,13 +3643,13 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
       header.pf.four_cc == 0x30315844) {   // 'DX10'
     // A DirectX 10 style texture, which has an additional header.
     func = read_dds_level_generic_uncompressed;
-    unsigned int format = dds.get_uint32();
+    unsigned int dxgi_format = dds.get_uint32();
     unsigned int dimension = dds.get_uint32();
     unsigned int misc_flag = dds.get_uint32();
     unsigned int array_size = dds.get_uint32();
     /*unsigned int alpha_mode = */dds.get_uint32();
 
-    switch (format) {
+    switch (dxgi_format) {
     case 2:    // DXGI_FORMAT_R32G32B32A32_FLOAT
       format = F_rgba32;
       component_type = T_float;
@@ -3665,6 +3665,11 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
       component_type = T_unsigned_short;
       func = read_dds_level_abgr16;
       break;
+    case 16:   // DXGI_FORMAT_R32G32_FLOAT
+      format = F_rg32;
+      component_type = T_float;
+      func = read_dds_level_raw;
+      break;
     case 27:   // DXGI_FORMAT_R8G8B8A8_TYPELESS
     case 28:   // DXGI_FORMAT_R8G8B8A8_UNORM
       format = F_rgba8;
@@ -3688,6 +3693,41 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
       component_type = T_byte;
       func = read_dds_level_abgr8;
       break;
+    case 34:   // DXGI_FORMAT_R16G16_FLOAT:
+      format = F_rg16;
+      component_type = T_half_float;
+      func = read_dds_level_raw;
+      break;
+    case 35:   // DXGI_FORMAT_R16G16_UNORM:
+      format = F_rg16;
+      component_type = T_unsigned_short;
+      func = read_dds_level_raw;
+      break;
+    case 37:   // DXGI_FORMAT_R16G16_SNORM:
+      format = F_rg16;
+      component_type = T_short;
+      func = read_dds_level_raw;
+      break;
+    case 40:   // DXGI_FORMAT_D32_FLOAT
+      format = F_depth_component32;
+      component_type = T_float;
+      func = read_dds_level_raw;
+      break;
+    case 41:   // DXGI_FORMAT_R32_FLOAT
+      format = F_r32;
+      component_type = T_float;
+      func = read_dds_level_raw;
+      break;
+    case 42:   // DXGI_FORMAT_R32_UINT
+      format = F_r32i;
+      component_type = T_unsigned_int;
+      func = read_dds_level_raw;
+      break;
+    case 43:   // DXGI_FORMAT_R32_SINT
+      format = F_r32i;
+      component_type = T_int;
+      func = read_dds_level_raw;
+      break;
     case 48:   // DXGI_FORMAT_R8G8_TYPELESS
     case 49:   // DXGI_FORMAT_R8G8_UNORM
       format = F_rg;
@@ -3703,6 +3743,36 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
       format = F_rg8i;
       component_type = T_byte;
       break;
+    case 54:   // DXGI_FORMAT_R16_FLOAT:
+      format = F_r16;
+      component_type = T_half_float;
+      func = read_dds_level_raw;
+      break;
+    case 55:   // DXGI_FORMAT_D16_UNORM:
+      format = F_depth_component16;
+      component_type = T_unsigned_short;
+      func = read_dds_level_raw;
+      break;
+    case 56:   // DXGI_FORMAT_R16_UNORM:
+      format = F_r16;
+      component_type = T_unsigned_short;
+      func = read_dds_level_raw;
+      break;
+    case 57:   // DXGI_FORMAT_R16_UINT:
+      format = F_r16i;
+      component_type = T_unsigned_short;
+      func = read_dds_level_raw;
+      break;
+    case 58:   // DXGI_FORMAT_R16_SNORM:
+      format = F_r16;
+      component_type = T_short;
+      func = read_dds_level_raw;
+      break;
+    case 59:   // DXGI_FORMAT_R16_SINT:
+      format = F_r16i;
+      component_type = T_short;
+      func = read_dds_level_raw;
+      break;
     case 60:   // DXGI_FORMAT_R8_TYPELESS
     case 61:   // DXGI_FORMAT_R8_UNORM
       format = F_red;
@@ -3760,7 +3830,6 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
       compression = CM_rgtc;
       func = read_dds_level_bc4;
       break;
-      break;
     case 82:   // DXGI_FORMAT_BC5_TYPELESS
     case 83:   // DXGI_FORMAT_BC5_UNORM
       format = F_rg;
@@ -3786,7 +3855,7 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
       break;
     default:
       gobj_cat.error()
-        << filename << ": unsupported DXGI format " << format << ".\n";
+        << filename << ": unsupported DXGI format " << dxgi_format << ".\n";
       return false;
     }
 
@@ -8264,6 +8333,7 @@ read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header, int n
 
   size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
   size_t row_bytes = x_size * 16;
+  nassertr(row_bytes * y_size == size, PTA_uchar());
   PTA_uchar image = PTA_uchar::empty_array(size);
   for (int y = y_size - 1; y >= 0; --y) {
     unsigned char *p = image.p() + y * row_bytes;
@@ -8280,6 +8350,26 @@ read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header, int n
   return image;
 }
 
+/**
+ * Called by read_dds for a DDS file that needs no transformations applied.
+ */
+PTA_uchar Texture::
+read_dds_level_raw(Texture *tex, CData *cdata, const DDSHeader &header, int n, istream &in) {
+  int x_size = tex->do_get_expected_mipmap_x_size(cdata, n);
+  int y_size = tex->do_get_expected_mipmap_y_size(cdata, n);
+
+  size_t size = tex->do_get_expected_ram_mipmap_page_size(cdata, n);
+  size_t row_bytes = x_size * cdata->_num_components * cdata->_component_width;
+  nassertr(row_bytes * y_size == size, PTA_uchar());
+  PTA_uchar image = PTA_uchar::empty_array(size);
+  for (int y = y_size - 1; y >= 0; --y) {
+    unsigned char *p = image.p() + y * row_bytes;
+    in.read((char *)p, row_bytes);
+  }
+
+  return image;
+}
+
 /**
  * Called by read_dds for a DDS file whose format isn't one we've specifically
  * optimized.

+ 2 - 0
panda/src/gobj/texture.h

@@ -817,6 +817,8 @@ private:
                                          int n, istream &in);
   static PTA_uchar read_dds_level_abgr32(Texture *tex, CData *cdata, const DDSHeader &header,
                                          int n, istream &in);
+  static PTA_uchar read_dds_level_raw(Texture *tex, CData *cdata, const DDSHeader &header,
+                                      int n, istream &in);
   static PTA_uchar read_dds_level_generic_uncompressed(Texture *tex, CData *cdata,
                                                        const DDSHeader &header,
                                                        int n, istream &in);