فهرست منبع

fix issues with texture compression of small, L8 textures

David Rose 17 سال پیش
والد
کامیت
c44da02cee

+ 39 - 4
panda/src/dxgsg8/dxTextureContext8.cxx

@@ -377,6 +377,15 @@ create_texture(DXScreenData &scrn) {
     }
   }
 
+  // We can't compress for some reason, so ensure the uncompressed
+  // image is ready to load.
+  if (texture_stored_compressed) {
+    tex->get_uncompressed_ram_image();
+    compression_mode = tex->get_ram_image_compression();
+    texture_stored_compressed = compression_mode != Texture::CM_off;
+    compress_texture = false;
+  }
+  
   // handle each target bitdepth separately.  might be less confusing
   // to reorg by num_color_channels (input type)
   switch (target_bpp) {
@@ -1001,11 +1010,37 @@ extract_texture_data() {
       return false;
     }
     
+    int x_size = tex->get_expected_mipmap_x_size(n);
     int y_size = tex->get_expected_mipmap_y_size(n);
-    int size = rect.Pitch * (y_size / div);
-    size = min(size, (int)tex->get_expected_ram_mipmap_image_size(n));
-    PTA_uchar image = PTA_uchar::empty_array(size);
-    memcpy(image.p(), rect.pBits, size);
+    PTA_uchar image;
+
+    if (compression == Texture::CM_off) {
+      // Uncompressed, but we have to respect the pitch.
+      int pitch = x_size * tex->get_num_components() * tex->get_component_width();
+      pitch = min(pitch, (int)rect.Pitch);
+      int size = pitch * y_size;
+      image = PTA_uchar::empty_array(size);
+      if (pitch == rect.Pitch) {
+        // Easy copy.
+        memcpy(image.p(), rect.pBits, size);
+      } else {
+        // Harder copy: we have to de-interleave DirectX's extra bytes
+        // on the end of each row.
+        unsigned char *dest = image.p();
+        unsigned char *source = (unsigned char *)rect.pBits;
+        for (int yi = 0; yi < y_size; ++yi) {
+          memcpy(dest, source, pitch);
+          dest += pitch;
+          source += rect.Pitch;
+        }
+      }
+
+    } else {
+      // Compressed; just copy the data verbatim.
+      int size = rect.Pitch * (y_size / div);
+      image = PTA_uchar::empty_array(size);
+      memcpy(image.p(), rect.pBits, size);
+    }
     
     _d3d_2d_texture->UnlockRect(n);
     if (n == 0) {

+ 40 - 5
panda/src/dxgsg9/dxTextureContext9.cxx

@@ -405,6 +405,15 @@ create_texture(DXScreenData &scrn) {
     }
   }
 
+  // We can't compress for some reason, so ensure the uncompressed
+  // image is ready to load.
+  if (texture_stored_compressed) {
+    tex->get_uncompressed_ram_image();
+    compression_mode = tex->get_ram_image_compression();
+    texture_stored_compressed = compression_mode != Texture::CM_off;
+    compress_texture = false;
+  }
+
   // handle each target bitdepth separately.  might be less confusing
   // to reorg by num_color_channels (input type, rather than desired
   // 1st target)
@@ -1236,12 +1245,38 @@ extract_texture_data(DXScreenData &screen) {
           << "Texture::LockRect() failed!  level = " << n << " " << D3DERRORSTRING(hr);
         return state;
       }
-
+    
+      int x_size = tex->get_expected_mipmap_x_size(n);
       int y_size = tex->get_expected_mipmap_y_size(n);
-      int size = rect.Pitch * (y_size / div);
-      size = min(size, (int)tex->get_expected_ram_mipmap_image_size(n));
-      PTA_uchar image = PTA_uchar::empty_array(size);
-      memcpy(image.p(), rect.pBits, size);
+      PTA_uchar image;
+      
+      if (compression == Texture::CM_off) {
+        // Uncompressed, but we have to respect the pitch.
+        int pitch = x_size * tex->get_num_components() * tex->get_component_width();
+        pitch = min(pitch, (int)rect.Pitch);
+        int size = pitch * y_size;
+        image = PTA_uchar::empty_array(size);
+        if (pitch == rect.Pitch) {
+          // Easy copy.
+          memcpy(image.p(), rect.pBits, size);
+        } else {
+          // Harder copy: we have to de-interleave DirectX's extra bytes
+          // on the end of each row.
+          unsigned char *dest = image.p();
+          unsigned char *source = (unsigned char *)rect.pBits;
+          for (int yi = 0; yi < y_size; ++yi) {
+            memcpy(dest, source, pitch);
+            dest += pitch;
+            source += rect.Pitch;
+          }
+        }
+        
+      } else {
+        // Compressed; just copy the data verbatim.
+        int size = rect.Pitch * (y_size / div);
+        image = PTA_uchar::empty_array(size);
+        memcpy(image.p(), rect.pBits, size);
+      }
 
       _d3d_2d_texture->UnlockRect(n);
       if (n == 0) {

+ 6 - 0
panda/src/gobj/config_gobj.cxx

@@ -82,6 +82,12 @@ ConfigVariableDouble texture_scale
           "scale factor is applied before textures-power-2 or "
           "max-texture-dimension."));
 
+ConfigVariableInt texture_scale_limit
+("texture-scale-limit", 4,
+ PRC_DESC("This specifies the limit below which texture-scale will not "
+          "reduce a texture image.  This is a single dimension which applies "
+          "to both X and Y."));
+
 ConfigVariableList exclude_texture_scale
 ("exclude-texture-scale", 
  PRC_DESC("This is a list of glob patterns for texture filenames "

+ 1 - 0
panda/src/gobj/config_gobj.h

@@ -49,6 +49,7 @@ EXPCL_PANDA_GOBJ istream &operator >> (istream &in, ShaderUtilization &sut);
 // Configure variables for gobj package.
 extern EXPCL_PANDA_GOBJ ConfigVariableInt max_texture_dimension;
 extern EXPCL_PANDA_GOBJ ConfigVariableDouble texture_scale;
+extern EXPCL_PANDA_GOBJ ConfigVariableInt texture_scale_limit;
 extern EXPCL_PANDA_GOBJ ConfigVariableList exclude_texture_scale;
 
 

+ 5 - 0
panda/src/gobj/texture.cxx

@@ -1817,6 +1817,11 @@ adjust_size(int &x_size, int &y_size, const string &name) {
   if (!exclude) {
     new_x_size = (int)cfloor(new_x_size * texture_scale + 0.5);
     new_y_size = (int)cfloor(new_y_size * texture_scale + 0.5);
+
+    // Don't auto-scale below 4 in either dimension.  This causes
+    // problems for DirectX and texture compression.
+    new_x_size = min(max(new_x_size, (int)texture_scale_limit), x_size);
+    new_y_size = min(max(new_y_size, (int)texture_scale_limit), y_size);
   }
 
   switch (get_textures_power_2()) {