Browse Source

fix crashing bug with compressed texture

David Rose 16 years ago
parent
commit
c07d10f74b

+ 5 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -8458,8 +8458,9 @@ upload_texture_image(CLP(TextureContext) *gtc,
       // we grab the mipmap pointer first, if it is NULL we grab the
       // normal mipmap image pointer which is a PTA_uchar
       const unsigned char *image_ptr = (unsigned char*)tex->get_ram_mipmap_pointer(n);
+      CPTA_uchar ptimage;
       if (image_ptr == (const unsigned char *)NULL) {
-        CPTA_uchar ptimage = tex->get_ram_mipmap_image(n);
+        ptimage = tex->get_ram_mipmap_image(n);
         if (ptimage == (const unsigned char *)NULL) {
           GLCAT.warning()
             << "No mipmap level " << n << " defined for " << tex->get_name()
@@ -8587,9 +8588,10 @@ upload_texture_image(CLP(TextureContext) *gtc,
     }
     
     for (int n = mipmap_bias; n < num_ram_mipmap_levels; ++n) {
- 	  const unsigned char * image_ptr = (unsigned char*)tex->get_ram_mipmap_pointer(n);
+      const unsigned char *image_ptr = (unsigned char*)tex->get_ram_mipmap_pointer(n);
+      CPTA_uchar ptimage;
       if (image_ptr == (const unsigned char *)NULL) {
-        CPTA_uchar ptimage = tex->get_ram_mipmap_image(n);
+        ptimage = tex->get_ram_mipmap_image(n);
         if (ptimage == (const unsigned char *)NULL) {
           GLCAT.warning()
             << "No mipmap level " << n << " defined for " << tex->get_name()

+ 11 - 0
panda/src/gobj/texture.I

@@ -2199,3 +2199,14 @@ have_textures_power_2() {
   return (_textures_power_2 != ATS_UNSPECIFIED);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::RamImage::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE Texture::RamImage::
+RamImage() :
+  _page_size(0),
+  _pointer_image(NULL)
+{
+}

+ 69 - 72
panda/src/gobj/texture.cxx

@@ -830,7 +830,6 @@ set_ram_image(CPTA_uchar image, Texture::CompressionMode compression,
   nassertv(compression != CM_off || image.size() == do_get_expected_ram_image_size());
   if (_ram_images.empty()) {
     _ram_images.push_back(RamImage());
-    _ram_images.back()._pointer_image = NULL;
   } else {
     do_clear_ram_mipmap_images();
   }
@@ -925,6 +924,71 @@ get_ram_mipmap_image(int n) {
   return CPTA_uchar(get_class_type());
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::get_ram_mipmap_pointer
+//       Access: Published
+//  Description: Similiar to get_ram_mipmap_image(), however, in this
+//               case the void pointer for the given ram image is
+//               returned.  This will be NULL unless it has been
+//               explicitly set.
+////////////////////////////////////////////////////////////////////
+void *Texture::
+get_ram_mipmap_pointer(int n) {
+  MutexHolder holder(_lock);
+  if (n < (int)_ram_images.size()) {
+    return _ram_images[n]._pointer_image;
+  }
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::set_ram_mipmap_pointer
+//       Access: Published
+//  Description: Sets an explicit void pointer as the texture's mipmap
+//               image for the indicated level.  This is a special
+//               call to direct a texture to reference some external
+//               image location, for instance from a webcam input.
+//
+//               The texture will henceforth reference this pointer
+//               directly, instead of its own internal storage; the
+//               user is responsible for ensuring the data at this
+//               address remains allocated and valid, and in the
+//               correct format, during the lifetime of the texture.
+////////////////////////////////////////////////////////////////////
+void Texture::
+set_ram_mipmap_pointer(int n, void *image, size_t page_size) {
+  MutexHolder holder(_lock);
+  nassertv(_ram_image_compression != CM_off || page_size == get_expected_ram_mipmap_image_size(n));
+
+  while (n >= (int)_ram_images.size()) {
+    _ram_images.push_back(RamImage());
+  }
+  //if (page_size == 0) {
+  //  page_size = image.size();
+  //}
+
+  _ram_images[n]._page_size = page_size; 
+  _ram_images[n]._image.clear();
+  _ram_images[n]._pointer_image = image;
+  ++_image_modified;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::set_ram_mipmap_pointer_from_int
+//       Access: Published
+//  Description: Accepts a raw pointer cast as an int, which is then
+//               passed to set_ram_mipmap_pointer(); see the
+//               documentation for that method.
+//
+//               This variant is particularly useful to set an
+//               external pointer from a language like Python, which
+//               doesn't support void pointers directly.
+////////////////////////////////////////////////////////////////////
+void Texture::
+set_ram_mipmap_pointer_from_int(long long pointer, int n, int page_size) {
+  set_ram_mipmap_pointer(n, (void*)pointer, (size_t)page_size);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::clear_ram_mipmap_image
 //       Access: Published
@@ -937,8 +1001,8 @@ clear_ram_mipmap_image(int n) {
   if (n >= (int)_ram_images.size()) {
     return;
   }
-  _ram_images[n]._image.clear();
   _ram_images[n]._page_size = 0;
+  _ram_images[n]._image.clear();
   _ram_images[n]._pointer_image = NULL;
 }
 
@@ -3260,8 +3324,8 @@ do_make_ram_image() {
   _ram_images.push_back(RamImage());
   _ram_images[0]._page_size = do_get_expected_ram_page_size();
   _ram_images[0]._image = PTA_uchar::empty_array(do_get_expected_ram_image_size(), get_class_type());
-  _ram_image_compression = CM_off;
   _ram_images[0]._pointer_image = NULL;
+  _ram_image_compression = CM_off;
   return _ram_images[0]._image;
 }
 
@@ -3293,13 +3357,11 @@ do_make_ram_mipmap_image(int n) {
 
   while (n >= (int)_ram_images.size()) {
     _ram_images.push_back(RamImage());
-    _ram_images.back()._page_size = 0;
-    _ram_images.back()._pointer_image = NULL;
   }
 
   _ram_images[n]._image = PTA_uchar::empty_array(do_get_expected_ram_mipmap_image_size(n), get_class_type());
-  _ram_images[n]._page_size = do_get_expected_ram_mipmap_page_size(n);
   _ram_images[n]._pointer_image = NULL;
+  _ram_images[n]._page_size = do_get_expected_ram_mipmap_page_size(n);
   return _ram_images[n]._image;
 }
 
@@ -3314,8 +3376,6 @@ do_set_ram_mipmap_image(int n, CPTA_uchar image, size_t page_size) {
 
   while (n >= (int)_ram_images.size()) {
     _ram_images.push_back(RamImage());
-    _ram_images.back()._page_size = 0;
-    _ram_images.back()._pointer_image = NULL;
   }
   if (page_size == 0) {
     page_size = image.size();
@@ -3324,72 +3384,12 @@ do_set_ram_mipmap_image(int n, CPTA_uchar image, size_t page_size) {
   if (_ram_images[n]._image != image ||
       _ram_images[n]._page_size != page_size) {
     _ram_images[n]._image = image.cast_non_const();
-    _ram_images[n]._page_size = page_size;
     _ram_images[n]._pointer_image = NULL;
+    _ram_images[n]._page_size = page_size;
     ++_image_modified;
   }
 }
 
-
-////////////////////////////////////////////////////////////////////
-//     Function: Texture::set_ram_mipmap_pointer
-//       Access: Published
-//  Description: Sets this textures ram pointer image.  This
-////
-//               
-////////////////////////////////////////////////////////////////////
-void Texture::
-set_ram_mipmap_pointer(int n, void *image, size_t page_size) {
-  nassertv(_ram_image_compression != CM_off || page_size == get_expected_ram_mipmap_image_size(n));
-
-  while (n >= (int)_ram_images.size()) {
-    _ram_images.push_back(RamImage());
-    _ram_images.back()._page_size = 0;
-    _ram_images.back()._pointer_image = NULL;
-  }
-  //if (page_size == 0) {
-  //  page_size = image.size();
-  //}
-
-  _ram_images[n]._page_size = page_size; 
-  _ram_images[n]._pointer_image = image;
-  ++_image_modified;
-}
-
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: Texture::set_ram_mipmap_pointer
-//       Access: Published
-//  Description: Takes in an int and casts it to a pointer which
-//               is then used as the textures raw pointer image
-////////////////////////////////////////////////////////////////////
-void Texture::
-set_ram_mipmap_pointer_from_int(long long pointer, int n, int page_size) {
-  set_ram_mipmap_pointer(n,(void*)pointer,(size_t)page_size);
-}
-
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: Texture::get_ram_mipmap_pointer
-//       Access: Published
-//  Description: Returns the system-RAM image data associated with the
-//               nth mipmap level, if present.  Returns NULL if the
-//               nth mipmap level is not present.
-//               Similiar to the function above, however, in this case
-//               the void pointer for the given ram image is 
-//               returned.  This will be NULL unless it has been
-//               explicitly set
-////////////////////////////////////////////////////////////////////
-void *Texture::
-get_ram_mipmap_pointer(int n) {
-  if (n < (int)_ram_images.size()) {
-    return _ram_images[n]._pointer_image;
-  }
-  return NULL;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::consider_auto_process_ram_image
 //       Access: Protected
@@ -4519,7 +4519,6 @@ do_generate_ram_mipmap_images() {
     int n = 0;
     while (x_size > 1 || y_size > 1 || z_size > 1) {
       _ram_images.push_back(RamImage());
-      _ram_images.back()._pointer_image = NULL;
       filter_3d_mipmap_level(_ram_images[n + 1], _ram_images[n],
                              x_size, y_size, z_size);
       x_size = max(x_size >> 1, 1);
@@ -4535,7 +4534,6 @@ do_generate_ram_mipmap_images() {
     int n = 0;
     while (x_size > 1 || y_size > 1) {
       _ram_images.push_back(RamImage());
-      _ram_images.back()._pointer_image = NULL;
       filter_2d_mipmap_pages(_ram_images[n + 1], _ram_images[n],
                              x_size, y_size);
       x_size = max(x_size >> 1, 1);
@@ -6092,7 +6090,6 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) {
     for (int n = 0; n < num_ram_images; ++n) {
       _ram_images.push_back(RamImage());
       _ram_images[n]._page_size = get_expected_ram_page_size();
-      _ram_images[n]._pointer_image = NULL;
       if (manager->get_file_minor_ver() >= 1) {
         _ram_images[n]._page_size = scan.get_uint32();
       }

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

@@ -336,7 +336,7 @@ PUBLISHED:
   INLINE size_t get_expected_ram_mipmap_image_size(int n) const;
   INLINE size_t get_expected_ram_mipmap_page_size(int n) const;
   CPTA_uchar get_ram_mipmap_image(int n);
-  void * get_ram_mipmap_pointer(int n);
+  void *get_ram_mipmap_pointer(int n);
   INLINE PTA_uchar modify_ram_mipmap_image(int n);
   INLINE PTA_uchar make_ram_mipmap_image(int n);
   void set_ram_mipmap_pointer(int n, void *image, size_t page_size = 0);
@@ -559,10 +559,14 @@ protected:
   // This nested class declaration is used below.
   class RamImage {
   public:
+    INLINE RamImage();
+
     PTA_uchar _image;
     size_t _page_size;
-    void *_pointer_image;   // we will allow the ram image to accept a void* (basically a block of memory)
-                            // instead of a PTA_uchar
+
+    // If _pointer_image is non-NULL, it represents an external block
+    // of memory that is used instead of the above PTA_uchar.
+    void *_pointer_image;
   };
 
 private: