From c07d10f74baf07f37816606435ad2fa3e2589823 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 9 Sep 2009 18:06:46 +0000 Subject: [PATCH] fix crashing bug with compressed texture --- .../glstuff/glGraphicsStateGuardian_src.cxx | 8 +- panda/src/gobj/texture.I | 11 ++ panda/src/gobj/texture.cxx | 141 +++++++++--------- panda/src/gobj/texture.h | 10 +- 4 files changed, 92 insertions(+), 78 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index dded634483..145904c5e0 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/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() diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 4da69b1825..4c3b674296 100644 --- a/panda/src/gobj/texture.I +++ b/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) +{ +} diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 0617f509e2..3a941f39d4 100644 --- a/panda/src/gobj/texture.cxx +++ b/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(); } diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index ccc202979e..2b4dd7e52b 100644 --- a/panda/src/gobj/texture.h +++ b/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: