Browse Source

fix texture reloads b/t opengl and directx

David Rose 17 years ago
parent
commit
6c16f96c94

+ 94 - 71
panda/src/dxgsg9/dxTextureContext9.cxx

@@ -123,6 +123,68 @@ create_texture(DXScreenData &scrn) {
   Texture *tex = get_texture();
   nassertr(IS_VALID_PTR(tex), false);
 
+  // Ensure the ram image is loaded, if available.
+  tex->get_ram_image();
+
+  DWORD orig_width = (DWORD)tex->get_x_size();
+  DWORD orig_height = (DWORD)tex->get_y_size();
+  DWORD orig_depth = (DWORD)tex->get_z_size();
+
+  // check for texture compression
+  bool texture_wants_compressed = false;
+  Texture::CompressionMode compression_mode = tex->get_ram_image_compression();
+  bool texture_stored_compressed = compression_mode != Texture::CM_off;
+  
+  if (texture_stored_compressed) {
+    texture_wants_compressed = true;  
+  } else {
+    if (tex->get_compression() == Texture::CM_off) {
+      // no compression
+    } else {    
+      if (tex->get_compression() == Texture::CM_default) {
+        // default = use "compressed-textures" config setting
+        if (compressed_textures) {
+          texture_wants_compressed = true;
+        }
+      } else {
+        texture_wants_compressed = true;
+      }
+    }  
+  }
+    
+  switch (tex->get_texture_type()) {
+    case Texture::TT_1d_texture:
+    case Texture::TT_2d_texture:
+    case Texture::TT_cube_map:
+      // no compression for render target textures, or very small
+      // textures
+      if (!tex->get_render_to_texture() &&
+          orig_width >= 4 && orig_height >= 4) {
+        if (texture_wants_compressed){
+          compress_texture = true;
+        }
+      }
+      break;
+    case Texture::TT_3d_texture:
+      // compression of 3d textures not supported by all video chips
+      break;
+  }
+
+  if (texture_stored_compressed && !compress_texture) {
+    // If we're going to need to reload the texture to get its
+    // uncompressed image, we'd better do so now, *before* we figure
+    // out the source format.  We have to do this early, even though
+    // we're going to do it again in fill_d3d_texture_pixels(),
+    // because sometimes reloading the original ram image will change
+    // the texture's apparent pixel format (the compressed form may
+    // have a different format than the uncompressed form).
+    tex->get_uncompressed_ram_image();
+
+    orig_width = (DWORD)tex->get_x_size();
+    orig_height = (DWORD)tex->get_y_size();
+    orig_depth = (DWORD)tex->get_z_size();
+  }
+
   // bpp indicates requested fmt, not texture fmt
   DWORD target_bpp = get_bits_per_pixel(tex->get_format(), &num_alpha_bits);
   DWORD num_color_channels = tex->get_num_components();
@@ -132,10 +194,6 @@ create_texture(DXScreenData &scrn) {
 
   //PRINT_REFCNT(dxgsg9, scrn._d3d9);
 
-  DWORD orig_width = (DWORD)tex->get_x_size();
-  DWORD orig_height = (DWORD)tex->get_y_size();
-  DWORD orig_depth = (DWORD)tex->get_z_size();
-
   if ((tex->get_format() == Texture::F_luminance_alpha)||
       (tex->get_format() == Texture::F_luminance_alphamask) ||
       (tex->get_format() == Texture::F_luminance)) {
@@ -173,49 +231,6 @@ create_texture(DXScreenData &scrn) {
     _d3d_format = D3DFMT_A8R8G8B8;
     break;
   }
-
-  // check for texture compression
-  bool texture_wants_compressed = false;
-  Texture::CompressionMode compression_mode = tex->get_ram_image_compression();
-  bool texture_stored_compressed = compression_mode != Texture::CM_off;
-  
-  if (texture_stored_compressed) {
-    texture_wants_compressed = true;  
-  }
-  else {
-    if (tex->get_compression() == Texture::CM_off) {
-      // no compression
-    }
-    else {    
-      if (tex->get_compression() == Texture::CM_default) {
-        // default = use "compressed-textures" config setting
-        if (compressed_textures) {
-          texture_wants_compressed = true;
-        }
-      }
-      else {
-        texture_wants_compressed = true;
-      }
-    }  
-  }
-    
-  switch (tex->get_texture_type()) {
-    case Texture::TT_1d_texture:
-    case Texture::TT_2d_texture:
-    case Texture::TT_cube_map:
-      // no compression for render target textures, or very small
-      // textures
-      if (!tex->get_render_to_texture() &&
-          orig_width >= 4 && orig_height >= 4) {
-        if (texture_wants_compressed){
-          compress_texture = true;
-        }
-      }
-      break;
-    case Texture::TT_3d_texture:
-      // compression of 3d textures not supported by all video chips
-      break;
-  }
   
   // make sure we handled all the possible cases
   nassertr(_d3d_format != D3DFMT_UNKNOWN, false);
@@ -813,10 +828,10 @@ create_texture(DXScreenData &scrn) {
   int data_size;
 
   data_size = target_width * target_height * target_depth;
-  data_size = (int) ((float) data_size * bytes_per_texel);
   if (_has_mipmaps) {
-    data_size = (int) ((float) data_size * 1.3f);
+    data_size = (int) ((float) data_size * 1.3333333f);
   }
+  data_size = (int) ((float) data_size * bytes_per_texel);
   if (tex->get_texture_type() == Texture::TT_cube_map) {
     data_size *= 6;
   }
@@ -829,6 +844,21 @@ create_texture(DXScreenData &scrn) {
       << "Creating " << *tex << ", " << data_size << " bytes, "
       << scrn._d3d_device->GetAvailableTextureMem()
       << " reported available.\n";
+    dxgsg9_cat.debug()
+      << " size is " << target_width << " w * " << target_height << " h * "
+      << target_depth << " d";
+    if (_has_mipmaps) {
+      dxgsg9_cat.debug(false)
+        << " * 1.3333333 mipmaps";
+    }
+    dxgsg9_cat.debug(false)
+      << " * " << bytes_per_texel << " bpt";
+    if (tex->get_texture_type() == Texture::TT_cube_map) {
+      dxgsg9_cat.debug(false)
+        << " * 6 faces";
+    }
+    dxgsg9_cat.debug(false)
+      << "\n";
   }
 
   attempts = 0;
@@ -879,7 +909,7 @@ create_texture(DXScreenData &scrn) {
       << " => " << D3DFormatStr(target_pixel_format) << endl;
   }
 
-  hr = fill_d3d_texture_pixels(scrn);
+  hr = fill_d3d_texture_pixels(scrn, compress_texture);
   if (FAILED(hr)) {
 
     dxgsg9_cat.debug ()
@@ -1650,7 +1680,7 @@ exit_FillMipmapSurf:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 HRESULT DXTextureContext9::
-fill_d3d_texture_pixels(DXScreenData &scrn) {
+fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture) {
   IDirect3DDevice9 *device = scrn._d3d_device;
   Texture *tex = get_texture();
   nassertr(IS_VALID_PTR(tex), E_FAIL);
@@ -1661,29 +1691,22 @@ fill_d3d_texture_pixels(DXScreenData &scrn) {
   HRESULT hr = E_FAIL;
 
   CPTA_uchar image;
-  if (scrn._dxgsg9->get_supports_compressed_texture()) {
+  Texture::CompressionMode image_compression = Texture::CM_off;
+  if (compress_texture) {
+    // If we are to be compressing this texture, accept a
+    // pre-compressed ram image if it is already so.
     image = tex->get_ram_image();
+    if (!image.is_null()) {
+      image_compression = tex->get_ram_image_compression();
+    }
   } else {
+    // If we are not to be compressing this texture, we can only
+    // accept an uncompressed ram image.  Ask the texture to give us
+    // one, so that there's no danger of accidentally getting a
+    // pre-compressed image.
     image = tex->get_uncompressed_ram_image();
   }
 
-  Texture::CompressionMode image_compression;
-  if (image.is_null()) {
-    image_compression = Texture::CM_off;
-  } else {
-    image_compression = tex->get_ram_image_compression();
-  }
-
-  if (!scrn._dxgsg9->get_supports_compressed_texture_format(image_compression) ||
-      tex->get_x_size() < 4 || tex->get_y_size() < 4) {
-    // If we don't support this particular compression method, or in
-    // any case if the texture is too small (DirectX won't accept a
-    // small compressed texture), then fetch and load the uncompressed
-    // version instead.
-    image = tex->get_uncompressed_ram_image();
-    image_compression = Texture::CM_off;
-  }    
-
   if (image.is_null()) {
     // The texture doesn't have an image to load.  That's ok; it
     // might be a texture we've rendered to by frame buffer
@@ -1750,7 +1773,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn) {
 
   DWORD orig_depth = (DWORD) tex->get_z_size();
   D3DFORMAT source_format = _d3d_format;
-  
+
   // check for compressed textures and adjust source_format accordingly
   switch (image_compression) {
   case Texture::CM_dxt1:
@@ -1772,7 +1795,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn) {
     // no known compression format.. no adjustment
     break;
   }
-  
+
   for (unsigned int di = 0; di < orig_depth; di++) {
     
     // fill top level mipmap

+ 1 - 1
panda/src/dxgsg9/dxTextureContext9.h

@@ -50,7 +50,7 @@ public:
 
 private:
   HRESULT fill_d3d_texture_mipmap_pixels(int mip_level, int depth_index, D3DFORMAT source_format);
-  HRESULT fill_d3d_texture_pixels(DXScreenData &scrn);
+  HRESULT fill_d3d_texture_pixels(DXScreenData &scrn, bool compress_texture);
   HRESULT fill_d3d_volume_texture_pixels(DXScreenData &scrn);
   static int down_to_power_2(int value);
   unsigned int get_bits_per_pixel(Texture::Format format, int *alphbits);

+ 8 - 2
panda/src/gobj/texture.cxx

@@ -2907,7 +2907,13 @@ do_unlock_and_reload_ram_image(bool allow_compression) {
   }
 
   // Then make sure we still need to reload before continuing.
-  if (_loaded_from_image && !do_has_ram_image() && !_fullpath.empty()) {
+  bool has_ram_image = do_has_ram_image();
+  if (has_ram_image && !allow_compression && get_ram_image_compression() != Texture::CM_off) {
+    // If we don't want compression, but the ram image we have is
+    // pre-compressed, we don't consider it.
+    has_ram_image = false;
+  }
+  if (_loaded_from_image && !has_ram_image && !_fullpath.empty()) {
     nassertv(!_reloading);
     _reloading = true;
 
@@ -2955,7 +2961,7 @@ do_reload_ram_image(bool allow_compression) {
     allow_compression = false;
   }
 
-  if ((cache->get_cache_textures() || (do_has_compression() && cache->get_cache_compressed_textures())) && !textures_header_only) {
+  if ((cache->get_cache_textures() || (allow_compression && cache->get_cache_compressed_textures())) && !textures_header_only) {
     // See if the texture can be found in the on-disk cache, if it is
     // active.