From 31091e89744416b9bc6c2cc3b8d5e6f33a36d29d Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 16 Jan 2009 21:31:17 +0000 Subject: [PATCH] fix texture bam issues --- panda/src/express/pointerToArray.I | 44 +++++++- panda/src/express/pointerToArray.h | 3 + panda/src/gobj/texture.I | 2 +- panda/src/gobj/texture.cxx | 164 ++++++++++++++++------------- panda/src/gobj/texture.h | 9 +- 5 files changed, 140 insertions(+), 82 deletions(-) diff --git a/panda/src/express/pointerToArray.I b/panda/src/express/pointerToArray.I index 22d8bcd12f..032972d174 100644 --- a/panda/src/express/pointerToArray.I +++ b/panda/src/express/pointerToArray.I @@ -427,6 +427,18 @@ v() const { return *((To *)(this->_void_ptr)); } +//////////////////////////////////////////////////////////////////// +// Function: PointerToArray::v0 +// Access: Public +// Description: To access the internal ReferenceCountedVector object, +// for very low-level fiddling. Know what you are doing! +//////////////////////////////////////////////////////////////////// +template +INLINE ReferenceCountedVector *PointerToArray:: +v0() const { + return (To *)(this->_void_ptr); +} + //////////////////////////////////////////////////////////////////// // Function: PointerToArray::get_element // Access: Published @@ -902,7 +914,7 @@ operator [](int n) const { template INLINE ConstPointerToArray:: operator const Element *() const { - To *vec = (To *)(this->_void_ptr); + const To *vec = (const To *)(this->_void_ptr); return ((vec == NULL)||(vec->empty())) ? (const Element *)NULL : &(vec->front()); } @@ -916,7 +928,7 @@ operator const Element *() const { template INLINE const Element *ConstPointerToArray:: p() const { - To *vec = (To *)(this->_void_ptr); + const To *vec = (const To *)(this->_void_ptr); return ((vec == NULL)||(vec->empty())) ? (const Element *)NULL : &(vec->front()); } @@ -932,7 +944,33 @@ v() const { nassertd((this->_void_ptr) != NULL) { ((ConstPointerToArray *)this)->reassign(new ReferenceCountedVector(_type_handle)); } - return *(To *)(this->_void_ptr); + return *(const To *)(this->_void_ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::v0 +// Access: Public +// Description: To access the internal ReferenceCountedVector object, +// for very low-level fiddling. Know what you are doing! +//////////////////////////////////////////////////////////////////// +template +INLINE const ReferenceCountedVector *ConstPointerToArray:: +v0() const { + return (const To *)(this->_void_ptr); +} + +//////////////////////////////////////////////////////////////////// +// Function: ConstPointerToArray::cast_non_const +// Access: Public +// Description: Casts away the constness of the CPTA(Element), and +// returns an equivalent PTA(Element). +//////////////////////////////////////////////////////////////////// +template +INLINE PointerToArray ConstPointerToArray:: +cast_non_const() const { + PointerToArray non_const; + non_const = (To *)(this->_void_ptr); + return non_const; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/express/pointerToArray.h b/panda/src/express/pointerToArray.h index 685573b3ec..dea3ea73c9 100644 --- a/panda/src/express/pointerToArray.h +++ b/panda/src/express/pointerToArray.h @@ -189,6 +189,7 @@ public: INLINE operator Element *() const; INLINE Element *p() const; INLINE pvector &v() const; + INLINE ReferenceCountedVector *v0() const; // Methods to help out Python and other high-level languages. INLINE const Element &get_element(size_type n) const; @@ -311,6 +312,8 @@ PUBLISHED: INLINE operator const Element *() const; INLINE const Element *p() const; INLINE const pvector &v() const; + INLINE const ReferenceCountedVector *v0() const; + INLINE PointerToArray cast_non_const() const; // Methods to help out Python and other high-level languages. INLINE const Element &get_element(size_type n) const; diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 0530410a6c..ac99c6be0e 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -1524,7 +1524,7 @@ get_simple_ram_image() const { // new_simple_ram_image(). //////////////////////////////////////////////////////////////////// INLINE void Texture:: -set_simple_ram_image(PTA_uchar image, int x_size, int y_size) { +set_simple_ram_image(CPTA_uchar image, int x_size, int y_size) { MutexHolder holder(_lock); do_set_simple_ram_image(image, x_size, y_size); } diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 5bd6088702..aca3a44170 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -775,7 +775,7 @@ load_related(const InternalName *suffix) const { // This does *not* affect keep_ram_image. //////////////////////////////////////////////////////////////////// void Texture:: -set_ram_image(PTA_uchar image, Texture::CompressionMode compression, +set_ram_image(CPTA_uchar image, Texture::CompressionMode compression, size_t page_size) { MutexHolder holder(_lock); nassertv(compression != CM_default); @@ -791,7 +791,7 @@ set_ram_image(PTA_uchar image, Texture::CompressionMode compression, if (_ram_images[0]._image != image || _ram_images[0]._page_size != page_size || _ram_image_compression != compression) { - _ram_images[0]._image = image; + _ram_images[0]._image = image.cast_non_const(); _ram_images[0]._page_size = page_size; _ram_image_compression = compression; ++_image_modified; @@ -887,7 +887,7 @@ get_ram_mipmap_image(int n) { // This does *not* affect keep_ram_image. //////////////////////////////////////////////////////////////////// void Texture:: -set_ram_mipmap_image(int n, PTA_uchar image, size_t page_size) { +set_ram_mipmap_image(int n, CPTA_uchar image, size_t page_size) { MutexHolder holder(_lock); nassertv(_ram_image_compression != CM_off || image.size() == do_get_expected_ram_mipmap_image_size(n)); @@ -901,7 +901,7 @@ set_ram_mipmap_image(int n, PTA_uchar image, size_t page_size) { if (_ram_images[n]._image != image || _ram_images[n]._page_size != page_size) { - _ram_images[n]._image = image; + _ram_images[n]._image = image.cast_non_const(); _ram_images[n]._page_size = page_size; ++_image_modified; } @@ -3990,14 +3990,14 @@ get_ram_image_as(const string &requested_format) { // Description: //////////////////////////////////////////////////////////////////// void Texture:: -do_set_simple_ram_image(PTA_uchar image, int x_size, int y_size) { +do_set_simple_ram_image(CPTA_uchar image, int x_size, int y_size) { nassertv(_texture_type == TT_2d_texture); size_t expected_page_size = (size_t)(x_size * y_size * 4); nassertv(image.size() == expected_page_size); _simple_x_size = x_size; _simple_y_size = y_size; - _simple_ram_image._image = image; + _simple_ram_image._image = image.cast_non_const(); _simple_ram_image._page_size = image.size(); _simple_image_date_generated = (PN_int32)time(NULL); ++_simple_image_modified; @@ -5597,7 +5597,15 @@ make_from_bam(const FactoryParams ¶ms) { me->_alpha_file_channel = alpha_file_channel; me->_texture_type = texture_type; + // Read the texture attributes directly from the bam stream. + me->fillin(scan, manager, has_rawdata); + } else { + // Now create a temporary Texture object to read all the + // attributes from the bam stream. + PT(Texture) dummy = new Texture(""); + dummy->fillin(scan, manager, has_rawdata); + if (filename.empty()) { // This texture has no filename; since we don't have an image to // load, we can't actually create the texture. @@ -5618,7 +5626,7 @@ make_from_bam(const FactoryParams ¶ms) { } LoaderOptions options = manager->get_loader_options(); - if (false) { // temporary hack standin + if (dummy->uses_mipmaps()) { options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps); } @@ -5645,19 +5653,12 @@ make_from_bam(const FactoryParams ¶ms) { break; } } + + if (me != (Texture *)NULL) { + me->set_name(name); + } } - if (me == (Texture *)NULL) { - // Oops, we couldn't load the texture; we'll just return NULL. - // But we do need a dummy texture to read in and ignore all of the - // attributes. - PT(Texture) dummy = new Texture(""); - dummy->fillin(scan, manager, has_rawdata); - - } else { - me->set_name(name); - me->fillin(scan, manager, has_rawdata); - } return me; } @@ -5673,61 +5674,37 @@ void Texture:: fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) { // We have already read in the filenames; don't read them again. - // Use the setters instead of setting these directly, so we can - // correctly avoid incrementing _properties_modified if none of - // these actually change. (Otherwise, we'd have to reload the - // texture to the GSG every time we loaded a new bam file that - // reference the texture, since each bam file reference passes - // through this function.) - - do_set_wrap_u((WrapMode)scan.get_uint8()); - do_set_wrap_v((WrapMode)scan.get_uint8()); - do_set_wrap_w((WrapMode)scan.get_uint8()); - do_set_minfilter((FilterType)scan.get_uint8()); - do_set_magfilter((FilterType)scan.get_uint8()); - do_set_anisotropic_degree(scan.get_int16()); - Colorf color; - color.read_datagram(scan); - do_set_border_color(color); + _wrap_u = (WrapMode)scan.get_uint8(); + _wrap_v = (WrapMode)scan.get_uint8(); + _wrap_w = (WrapMode)scan.get_uint8(); + _minfilter = (FilterType)scan.get_uint8(); + _magfilter = (FilterType)scan.get_uint8(); + _anisotropic_degree = scan.get_int16(); + _border_color.read_datagram(scan); if (manager->get_file_minor_ver() >= 1) { - do_set_compression((CompressionMode)scan.get_uint8()); + _compression = (CompressionMode)scan.get_uint8(); } if (manager->get_file_minor_ver() >= 16) { - do_set_quality_level((QualityLevel)scan.get_uint8()); + _quality_level = (QualityLevel)scan.get_uint8(); } - Format format = (Format)scan.get_uint8(); - int num_components = scan.get_uint8(); - - if (num_components == _num_components) { - // Only reset the format if the number of components hasn't - // changed, since if the number of components has changed our - // texture no longer matches what it was when the bam was - // written. - do_set_format(format); - } + _format = (Format)scan.get_uint8(); + _num_components = scan.get_uint8(); + ++_properties_modified; bool has_simple_ram_image = false; if (manager->get_file_minor_ver() >= 18) { - if (has_rawdata || (_orig_file_x_size == 0 && _orig_file_y_size == 0)) { - // We only trust the file size if we have the raw data. - _orig_file_x_size = scan.get_uint32(); - _orig_file_y_size = scan.get_uint32(); - } else { - // Discard the file size indicated in the bam file; it might not - // be accurate. - scan.get_uint32(); - scan.get_uint32(); - } + _orig_file_x_size = scan.get_uint32(); + _orig_file_y_size = scan.get_uint32(); has_simple_ram_image = scan.get_bool(); } if (has_simple_ram_image) { - int x_size = scan.get_uint32(); - int y_size = scan.get_uint32(); - PN_int32 date_generated = scan.get_int32(); + _simple_x_size = scan.get_uint32(); + _simple_y_size = scan.get_uint32(); + _simple_image_date_generated = scan.get_int32(); size_t u_size = scan.get_uint32(); PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type()); @@ -5735,23 +5712,12 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) { image[(int)u_idx] = scan.get_uint8(); } - // Only replace the simple ram image if it was generated more - // recently than the one we already have. - if (_simple_ram_image._image.empty() || - date_generated > _simple_image_date_generated) { - _simple_x_size = x_size; - _simple_y_size = y_size; - _simple_image_date_generated = date_generated; - _simple_ram_image._image = image; - _simple_ram_image._page_size = u_size; - ++_simple_image_modified; - } + _simple_ram_image._image = image; + _simple_ram_image._page_size = u_size; + ++_simple_image_modified; } if (has_rawdata) { - // In the rawdata case, we must always set the format. - _format = format; - _num_components = num_components; _x_size = scan.get_uint32(); _y_size = scan.get_uint32(); _z_size = scan.get_uint32(); @@ -5788,10 +5754,60 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) { _loaded_from_image = true; do_set_pad_size(0, 0, 0); ++_image_modified; - ++_properties_modified; } } +//////////////////////////////////////////////////////////////////// +// Function: Texture::fillin_from +// Access: Protected +// Description: Called in make_from_bam(), this method properly +// copies the attributes from the bam stream (as stored +// in dummy) into this texture, updating the modified +// flags appropriately. +//////////////////////////////////////////////////////////////////// +void Texture:: +fillin_from(Texture *dummy) { + // Use the setters instead of setting these directly, so we can + // correctly avoid incrementing _properties_modified if none of + // these actually change. (Otherwise, we'd have to reload the + // texture to the GSG every time we loaded a new bam file that + // reference the texture, since each bam file reference passes + // through this function.) + + do_set_wrap_u(dummy->get_wrap_u()); + do_set_wrap_v(dummy->get_wrap_v()); + do_set_wrap_w(dummy->get_wrap_w()); + do_set_minfilter(dummy->get_minfilter()); + do_set_magfilter(dummy->get_magfilter()); + do_set_anisotropic_degree(dummy->get_anisotropic_degree()); + do_set_border_color(dummy->get_border_color()); + do_set_compression(dummy->get_compression()); + do_set_quality_level(dummy->get_quality_level()); + + Format format = dummy->get_format(); + int num_components = dummy->get_num_components(); + + if (num_components == _num_components) { + // Only reset the format if the number of components hasn't + // changed, since if the number of components has changed our + // texture no longer matches what it was when the bam was + // written. + do_set_format(format); + } + + if (dummy->has_simple_ram_image()) { + // Only replace the simple ram image if it was generated more + // recently than the one we already have. + if (_simple_ram_image._image.empty() || + dummy->_simple_image_date_generated > _simple_image_date_generated) { + do_set_simple_ram_image(dummy->get_simple_ram_image(), + dummy->get_simple_x_size(), + dummy->get_simple_y_size()); + _simple_image_date_generated = dummy->_simple_image_date_generated; + } + } +} + //////////////////////////////////////////////////////////////////// // Function: Texture::write_datagram // Access: Public diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 655c7d6d52..7bce67921f 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -307,7 +307,7 @@ PUBLISHED: CPTA_uchar get_ram_image_as(const string &requested_format); INLINE PTA_uchar modify_ram_image(); INLINE PTA_uchar make_ram_image(); - void set_ram_image(PTA_uchar image, CompressionMode compression = CM_off, + void set_ram_image(CPTA_uchar image, CompressionMode compression = CM_off, size_t page_size = 0); INLINE void clear_ram_image(); INLINE void set_keep_ram_image(bool keep_ram_image); @@ -329,7 +329,7 @@ PUBLISHED: CPTA_uchar get_ram_mipmap_image(int n); INLINE PTA_uchar modify_ram_mipmap_image(int n); INLINE PTA_uchar make_ram_mipmap_image(int n); - void set_ram_mipmap_image(int n, PTA_uchar image, size_t page_size = 0); + void set_ram_mipmap_image(int n, CPTA_uchar image, size_t page_size = 0); void clear_ram_mipmap_image(int n); INLINE void clear_ram_mipmap_images(); INLINE void generate_ram_mipmap_images(); @@ -339,7 +339,7 @@ PUBLISHED: INLINE bool has_simple_ram_image() const; INLINE size_t get_simple_ram_image_size() const; INLINE CPTA_uchar get_simple_ram_image() const; - INLINE void set_simple_ram_image(PTA_uchar image, int x_size, int y_size); + INLINE void set_simple_ram_image(CPTA_uchar image, int x_size, int y_size); PTA_uchar modify_simple_ram_image(); PTA_uchar new_simple_ram_image(int x_size, int y_size); void generate_simple_ram_image(); @@ -520,7 +520,7 @@ protected: virtual bool do_has_uncompressed_ram_image() const; CPTA_uchar do_get_ram_image(); CPTA_uchar do_get_uncompressed_ram_image(); - void do_set_simple_ram_image(PTA_uchar image, int x_size, int y_size); + void do_set_simple_ram_image(CPTA_uchar image, int x_size, int y_size); INLINE size_t do_get_ram_image_size() const; INLINE bool do_has_ram_mipmap_image(int n) const; int do_get_expected_num_mipmap_levels() const; @@ -734,6 +734,7 @@ public: protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata); + void fillin_from(Texture *dummy); public: static TypeHandle get_class_type() {