Browse Source

don't crash if loading cached compressed textures and compression unsupported

David Rose 17 years ago
parent
commit
59b5ab684d

+ 2 - 1
panda/src/display/graphicsStateGuardian.cxx

@@ -2214,6 +2214,7 @@ void GraphicsStateGuardian::
 async_reload_texture(TextureContext *tc) {
 async_reload_texture(TextureContext *tc) {
   nassertv(_loader != (Loader *)NULL);
   nassertv(_loader != (Loader *)NULL);
 
 
-  PT(AsyncTask) request = new TextureReloadRequest(tc);
+  PT(AsyncTask) request = 
+    new TextureReloadRequest(tc, _supports_compressed_texture);
   _loader->load_async(request);
   _loader->load_async(request);
 }
 }

+ 24 - 12
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -6772,22 +6772,29 @@ bool CLP(GraphicsStateGuardian)::
 upload_texture(CLP(TextureContext) *gtc) {
 upload_texture(CLP(TextureContext) *gtc) {
   Texture *tex = gtc->get_texture();
   Texture *tex = gtc->get_texture();
 
 
-  if (_incomplete_render && 
-      !tex->has_ram_image() && tex->might_have_ram_image() &&
-      tex->has_simple_ram_image() &&
-      !_loader.is_null()) {
-    // If we don't have the texture data right now, go get it, but in
-    // the meantime load a temporary simple image in its place.
-    async_reload_texture(gtc);
-    if (!tex->has_ram_image()) {
-      if (gtc->was_simple_image_modified()) {
-        return upload_simple_texture(gtc);
+  if (_incomplete_render) {
+    bool has_image = _supports_compressed_texture ? tex->has_ram_image() : tex->has_uncompressed_ram_image();
+    if (!has_image && tex->might_have_ram_image() &&
+        tex->has_simple_ram_image() &&
+        !_loader.is_null()) {
+      // If we don't have the texture data right now, go get it, but in
+      // the meantime load a temporary simple image in its place.
+      async_reload_texture(gtc);
+      if (!tex->has_ram_image()) {
+        if (gtc->was_simple_image_modified()) {
+          return upload_simple_texture(gtc);
+        }
+        return true;
       }
       }
-      return true;
     }
     }
   }
   }
 
 
-  CPTA_uchar image = tex->get_ram_image();
+  CPTA_uchar image;
+  if (_supports_compressed_texture) {
+    image = tex->get_ram_image();
+  } else {
+    image = tex->get_uncompressed_ram_image();
+  }
 
 
   Texture::CompressionMode image_compression;
   Texture::CompressionMode image_compression;
   if (image.is_null()) {
   if (image.is_null()) {
@@ -6796,6 +6803,11 @@ upload_texture(CLP(TextureContext) *gtc) {
     image_compression = tex->get_ram_image_compression();
     image_compression = tex->get_ram_image_compression();
   }
   }
 
 
+  if (!get_supports_compressed_texture_format(image_compression)) {
+    image = tex->get_uncompressed_ram_image();
+    image_compression = Texture::CM_off;
+  }    
+
   int mipmap_bias = 0;
   int mipmap_bias = 0;
 
 
   int width = tex->get_x_size();
   int width = tex->get_x_size();

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

@@ -1032,7 +1032,7 @@ bool Texture::
 reload() {
 reload() {
   ReMutexHolder holder(_lock);
   ReMutexHolder holder(_lock);
   if (_loaded_from_image && has_filename()) {
   if (_loaded_from_image && has_filename()) {
-    reload_ram_image();
+    reload_ram_image(true);
     ++_image_modified;
     ++_image_modified;
     return has_ram_image();
     return has_ram_image();
   }
   }
@@ -1381,6 +1381,19 @@ has_ram_image() const {
   return !_ram_images.empty() && !_ram_images[0]._image.empty();
   return !_ram_images.empty() && !_ram_images[0]._image.empty();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::has_uncompressed_ram_image
+//       Access: Published, Virtual
+//  Description: Returns true if the Texture has its image contents
+//               available in main RAM and is uncompressed, false
+//               otherwise.  See has_ram_image().
+////////////////////////////////////////////////////////////////////
+bool Texture::
+has_uncompressed_ram_image() const {
+  ReMutexHolder holder(_lock);
+  return !_ram_images.empty() && !_ram_images[0]._image.empty() && _ram_image_compression == CM_off;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::get_ram_image
 //     Function: Texture::get_ram_image
 //       Access: Published
 //       Access: Published
@@ -1413,7 +1426,7 @@ CPTA_uchar Texture::
 get_ram_image() {
 get_ram_image() {
   ReMutexHolder holder(_lock);
   ReMutexHolder holder(_lock);
   if (_loaded_from_image && !has_ram_image() && has_filename()) {
   if (_loaded_from_image && !has_ram_image() && has_filename()) {
-    reload_ram_image();
+    reload_ram_image(true);
   }
   }
 
 
   if (_ram_images.empty()) {
   if (_ram_images.empty()) {
@@ -1423,6 +1436,39 @@ get_ram_image() {
   return _ram_images[0]._image;
   return _ram_images[0]._image;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::get_uncompressed_ram_image
+//       Access: Published
+//  Description: Returns the system-RAM image associated with the
+//               texture, in an uncompressed form if at all possible.
+//
+//               If get_ram_image_compression() is CM_off, then the
+//               system-RAM image is already uncompressed, and this
+//               returns the same thing as get_ram_image().
+//
+//               If get_ram_image_compression() is anything else, then
+//               the system-RAM image is compressed.  In this case,
+//               the image will be reloaded from the *original* file
+//               (not from the cache), in the hopes that an
+//               uncompressed image will be found there.
+//
+//               If an uncompressed image cannot be found, returns
+//               NULL.
+////////////////////////////////////////////////////////////////////
+CPTA_uchar Texture::
+get_uncompressed_ram_image() {
+  ReMutexHolder holder(_lock);
+  if (_loaded_from_image && (!has_ram_image() || get_ram_image_compression() != CM_off) && has_filename()) {
+    reload_ram_image(false);
+  }
+
+  if (_ram_images.empty() || get_ram_image_compression() != CM_off) {
+    return CPTA_uchar(get_class_type());
+  }
+
+  return _ram_images[0]._image;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::set_ram_image
 //     Function: Texture::set_ram_image
 //       Access: Published
 //       Access: Published
@@ -3094,10 +3140,14 @@ reconsider_dirty() {
 //               available, if possible.
 //               available, if possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void Texture::
 void Texture::
-reload_ram_image() {
+reload_ram_image(bool allow_compression) {
   BamCache *cache = BamCache::get_global_ptr();
   BamCache *cache = BamCache::get_global_ptr();
   PT(BamCacheRecord) record;
   PT(BamCacheRecord) record;
 
 
+  if (!has_compression()) {
+    allow_compression = false;
+  }
+
   if ((cache->get_cache_textures() || (has_compression() && cache->get_cache_compressed_textures())) && !textures_header_only) {
   if ((cache->get_cache_textures() || (has_compression() && cache->get_cache_compressed_textures())) && !textures_header_only) {
     // See if the texture can be found in the on-disk cache, if it is
     // See if the texture can be found in the on-disk cache, if it is
     // active.
     // active.
@@ -3123,7 +3173,7 @@ reload_ram_image() {
       } else {
       } else {
         // Also don't keep the cached version if it's compressed but
         // Also don't keep the cached version if it's compressed but
         // we want uncompressed.
         // we want uncompressed.
-        if (!has_compression() && tex->get_ram_image_compression() != Texture::CM_off) {
+        if (!allow_compression && tex->get_ram_image_compression() != Texture::CM_off) {
           if (gobj_cat.is_debug()) {
           if (gobj_cat.is_debug()) {
             gobj_cat.debug()
             gobj_cat.debug()
               << "Cached texture " << *this
               << "Cached texture " << *this

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

@@ -293,6 +293,7 @@ PUBLISHED:
   int get_expected_mipmap_z_size(int n) const;
   int get_expected_mipmap_z_size(int n) const;
 
 
   virtual bool has_ram_image() const;
   virtual bool has_ram_image() const;
+  virtual bool has_uncompressed_ram_image() const;
   INLINE bool might_have_ram_image() const;
   INLINE bool might_have_ram_image() const;
   INLINE size_t get_ram_image_size() const;
   INLINE size_t get_ram_image_size() const;
   INLINE size_t get_ram_page_size() const;
   INLINE size_t get_ram_page_size() const;
@@ -300,6 +301,7 @@ PUBLISHED:
   INLINE size_t get_expected_ram_page_size() const;
   INLINE size_t get_expected_ram_page_size() const;
   CPTA_uchar get_ram_image();
   CPTA_uchar get_ram_image();
   INLINE CompressionMode get_ram_image_compression() const;
   INLINE CompressionMode get_ram_image_compression() const;
+  CPTA_uchar get_uncompressed_ram_image();
   INLINE PTA_uchar modify_ram_image();
   INLINE PTA_uchar modify_ram_image();
   INLINE PTA_uchar make_ram_image();
   INLINE PTA_uchar make_ram_image();
   void set_ram_image(PTA_uchar image, CompressionMode compression = CM_off,
   void set_ram_image(PTA_uchar image, CompressionMode compression = CM_off,
@@ -442,7 +444,7 @@ protected:
   bool do_store_one(PNMImage &pnmimage, int z, int n) const;
   bool do_store_one(PNMImage &pnmimage, int z, int n) const;
 
 
   virtual void reconsider_dirty();
   virtual void reconsider_dirty();
-  virtual void reload_ram_image();
+  virtual void reload_ram_image(bool allow_compression);
 
 
   void do_modify_ram_image();
   void do_modify_ram_image();
   void do_make_ram_image();
   void do_make_ram_image();

+ 13 - 1
panda/src/pgraph/textureReloadRequest.I

@@ -20,8 +20,9 @@
 //               via load_async(), to begin an asynchronous load.
 //               via load_async(), to begin an asynchronous load.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE TextureReloadRequest::
 INLINE TextureReloadRequest::
-TextureReloadRequest(TextureContext *tc) :
+TextureReloadRequest(TextureContext *tc, bool allow_compressed) :
   _texture_context(tc),
   _texture_context(tc),
+  _allow_compressed(allow_compressed),
   _is_ready(false)
   _is_ready(false)
 {
 {
   nassertv(_texture_context != (TextureContext *)NULL);
   nassertv(_texture_context != (TextureContext *)NULL);
@@ -39,6 +40,17 @@ get_texture_context() const {
   return _texture_context;
   return _texture_context;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TextureReloadRequest::get_allow_compressed
+//       Access: Published
+//  Description: Returns the "allow compressed" flag associated with
+//               this asynchronous TextureReloadRequest.
+////////////////////////////////////////////////////////////////////
+INLINE bool TextureReloadRequest::
+get_allow_compressed() const {
+  return _allow_compressed;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TextureReloadRequest::is_ready
 //     Function: TextureReloadRequest::is_ready
 //       Access: Published
 //       Access: Published

+ 5 - 1
panda/src/pgraph/textureReloadRequest.cxx

@@ -26,7 +26,11 @@ bool TextureReloadRequest::
 do_task() {
 do_task() {
   // Don't reload the texture if it doesn't need it.
   // Don't reload the texture if it doesn't need it.
   if (_texture_context->was_image_modified()) {
   if (_texture_context->was_image_modified()) {
-    _texture->get_ram_image();
+    if (_allow_compressed) {
+      _texture->get_ram_image();
+    } else {
+      _texture->get_uncompressed_ram_image();
+    }
   }
   }
   _is_ready = true;
   _is_ready = true;
 
 

+ 3 - 1
panda/src/pgraph/textureReloadRequest.h

@@ -35,9 +35,10 @@ public:
   ALLOC_DELETED_CHAIN(TextureReloadRequest);
   ALLOC_DELETED_CHAIN(TextureReloadRequest);
 
 
 PUBLISHED:
 PUBLISHED:
-  INLINE TextureReloadRequest(TextureContext *tc);
+  INLINE TextureReloadRequest(TextureContext *tc, bool allow_compressed);
   
   
   INLINE TextureContext *get_texture_context() const;
   INLINE TextureContext *get_texture_context() const;
+  INLINE bool get_allow_compressed() const;
   INLINE bool is_ready() const;
   INLINE bool is_ready() const;
   
   
 protected:
 protected:
@@ -45,6 +46,7 @@ protected:
   
   
 private:
 private:
   TextureContext *_texture_context;
   TextureContext *_texture_context;
+  bool _allow_compressed;
   PT(Texture) _texture;
   PT(Texture) _texture;
   bool _is_ready;
   bool _is_ready;
   
   

+ 2 - 2
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -2013,7 +2013,7 @@ upload_texture(TinyTextureContext *gtc) {
   Texture *tex = gtc->get_texture();
   Texture *tex = gtc->get_texture();
 
 
   if (_incomplete_render && 
   if (_incomplete_render && 
-      !tex->has_ram_image() && tex->might_have_ram_image() &&
+      !tex->has_uncompressed_ram_image() && tex->might_have_ram_image() &&
       tex->has_simple_ram_image() &&
       tex->has_simple_ram_image() &&
       !_loader.is_null()) {
       !_loader.is_null()) {
     // If we don't have the texture data right now, go get it, but in
     // If we don't have the texture data right now, go get it, but in
@@ -2028,7 +2028,7 @@ upload_texture(TinyTextureContext *gtc) {
   }
   }
 
 
   PStatTimer timer(_load_texture_pcollector);
   PStatTimer timer(_load_texture_pcollector);
-  CPTA_uchar src_image = tex->get_ram_image();
+  CPTA_uchar src_image = tex->get_uncompressed_ram_image();
   if (src_image.is_null()) {
   if (src_image.is_null()) {
     return false;
     return false;
   }
   }