|
|
@@ -680,8 +680,12 @@ get_aux_data(const string &key) const {
|
|
|
// Description: Reads the texture from a Panda texture object. This
|
|
|
// defines the complete Texture specification, including
|
|
|
// the image data as well as all texture properties.
|
|
|
+// This only works if the txo file contains a static
|
|
|
+// Texture image, as opposed to a subclass of Texture
|
|
|
+// such as a movie texture.
|
|
|
//
|
|
|
-// The filename is just for reference.
|
|
|
+// Pass a real filename if it is available, or empty
|
|
|
+// string if it is not.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool Texture::
|
|
|
read_txo(istream &in, const string &filename) {
|
|
|
@@ -691,6 +695,79 @@ read_txo(istream &in, const string &filename) {
|
|
|
return do_read_txo(in, filename);
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::make_from_txo
|
|
|
+// Access: Published, Static
|
|
|
+// Description: Constructs a new Texture object from the txo file.
|
|
|
+// This is similar to Texture::read_txo(), but it
|
|
|
+// constructs and returns a new object, which allows it
|
|
|
+// to return a subclass of Texture (for instance, a
|
|
|
+// movie texture).
|
|
|
+//
|
|
|
+// Pass a real filename if it is available, or empty
|
|
|
+// string if it is not.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+PT(Texture) Texture::
|
|
|
+make_from_txo(istream &in, const string &filename) {
|
|
|
+ DatagramInputFile din;
|
|
|
+
|
|
|
+ if (!din.open(in, filename)) {
|
|
|
+ gobj_cat.error()
|
|
|
+ << "Could not read texture object: " << filename << "\n";
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ string head;
|
|
|
+ if (!din.read_header(head, _bam_header.size())) {
|
|
|
+ gobj_cat.error()
|
|
|
+ << filename << " is not a texture object file.\n";
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (head != _bam_header) {
|
|
|
+ gobj_cat.error()
|
|
|
+ << filename << " is not a texture object file.\n";
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ BamReader reader(&din);
|
|
|
+ if (!reader.init()) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ TypedWritable *object = reader.read_object();
|
|
|
+
|
|
|
+ if (object != (TypedWritable *)NULL &&
|
|
|
+ object->is_exact_type(BamCacheRecord::get_class_type())) {
|
|
|
+ // Here's a special case: if the first object in the file is a
|
|
|
+ // BamCacheRecord, it's really a cache data file and not a true
|
|
|
+ // txo file; but skip over the cache data record and let the user
|
|
|
+ // treat it like an ordinary txo file.
|
|
|
+ object = reader.read_object();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (object == (TypedWritable *)NULL) {
|
|
|
+ gobj_cat.error()
|
|
|
+ << "Texture object " << filename << " is empty.\n";
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ } else if (!object->is_of_type(Texture::get_class_type())) {
|
|
|
+ gobj_cat.error()
|
|
|
+ << "Texture object " << filename << " contains a "
|
|
|
+ << object->get_type() << ", not a Texture.\n";
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ PT(Texture) other = DCAST(Texture, object);
|
|
|
+ if (!reader.resolve()) {
|
|
|
+ gobj_cat.error()
|
|
|
+ << "Unable to fully resolve texture object file.\n";
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return other;
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Texture::write_txo
|
|
|
// Access: Published
|
|
|
@@ -990,6 +1067,20 @@ get_keep_ram_image() const {
|
|
|
return _keep_ram_image;
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::is_cacheable
|
|
|
+// Access: Published, Virtual
|
|
|
+// Description: Returns true if there is enough information in this
|
|
|
+// Texture object to write it to the bam cache
|
|
|
+// successfully, false otherwise. For most textures,
|
|
|
+// this is the same as has_ram_image().
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool Texture::
|
|
|
+is_cacheable() const {
|
|
|
+ MutexHolder holder(_lock);
|
|
|
+ return do_has_bam_rawdata();
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Texture::get_num_loadable_ram_mipmap_images
|
|
|
// Access: Published
|
|
|
@@ -3110,59 +3201,8 @@ do_read_txo_file(const Filename &fullpath) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool Texture::
|
|
|
do_read_txo(istream &in, const string &filename) {
|
|
|
- DatagramInputFile din;
|
|
|
-
|
|
|
- if (!din.open(in)) {
|
|
|
- gobj_cat.error()
|
|
|
- << "Could not read texture object: " << filename << "\n";
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- string head;
|
|
|
- if (!din.read_header(head, _bam_header.size())) {
|
|
|
- gobj_cat.error()
|
|
|
- << filename << " is not a texture object file.\n";
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (head != _bam_header) {
|
|
|
- gobj_cat.error()
|
|
|
- << filename << " is not a texture object file.\n";
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- BamReader reader(&din, filename);
|
|
|
- if (!reader.init()) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- TypedWritable *object = reader.read_object();
|
|
|
-
|
|
|
- if (object != (TypedWritable *)NULL &&
|
|
|
- object->is_exact_type(BamCacheRecord::get_class_type())) {
|
|
|
- // Here's a special case: if the first object in the file is a
|
|
|
- // BamCacheRecord, it's really a cache data file and not a true
|
|
|
- // txo file; but skip over the cache data record and let the user
|
|
|
- // treat it like an ordinary txo file.
|
|
|
- object = reader.read_object();
|
|
|
- }
|
|
|
-
|
|
|
- if (object == (TypedWritable *)NULL) {
|
|
|
- gobj_cat.error()
|
|
|
- << "Texture object " << filename << " is empty.\n";
|
|
|
- return false;
|
|
|
-
|
|
|
- } else if (!object->is_of_type(Texture::get_class_type())) {
|
|
|
- gobj_cat.error()
|
|
|
- << "Texture object " << filename << " contains a "
|
|
|
- << object->get_type() << ", not a Texture.\n";
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- PT(Texture) other = DCAST(Texture, object);
|
|
|
- if (!reader.resolve()) {
|
|
|
- gobj_cat.error()
|
|
|
- << "Unable to fully resolve texture object file.\n";
|
|
|
+ PT(Texture) other = make_from_txo(in, filename);
|
|
|
+ if (other == (Texture *)NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -3506,10 +3546,10 @@ do_read_dds(istream &in, const string &filename, bool header_only) {
|
|
|
bool Texture::
|
|
|
do_write(const Filename &fullpath, int z, int n, bool write_pages, bool write_mipmaps) const {
|
|
|
if (is_txo_filename(fullpath)) {
|
|
|
- if (!do_has_ram_image()) {
|
|
|
- ((Texture *)this)->do_get_ram_image();
|
|
|
+ if (!do_has_bam_rawdata()) {
|
|
|
+ ((Texture *)this)->do_get_bam_rawdata();
|
|
|
}
|
|
|
- nassertr(do_has_ram_image(), false);
|
|
|
+ nassertr(do_has_bam_rawdata(), false);
|
|
|
return do_write_txo_file(fullpath);
|
|
|
}
|
|
|
|
|
|
@@ -3671,7 +3711,7 @@ bool Texture::
|
|
|
do_write_txo(ostream &out, const string &filename) const {
|
|
|
DatagramOutputFile dout;
|
|
|
|
|
|
- if (!dout.open(out)) {
|
|
|
+ if (!dout.open(out, filename)) {
|
|
|
gobj_cat.error()
|
|
|
<< "Could not write texture object: " << filename << "\n";
|
|
|
return false;
|
|
|
@@ -3683,7 +3723,7 @@ do_write_txo(ostream &out, const string &filename) const {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- BamWriter writer(&dout, filename);
|
|
|
+ BamWriter writer(&dout);
|
|
|
if (!writer.init()) {
|
|
|
return false;
|
|
|
}
|
|
|
@@ -3700,7 +3740,7 @@ do_write_txo(ostream &out, const string &filename) const {
|
|
|
}
|
|
|
_lock.acquire();
|
|
|
|
|
|
- if (!do_has_ram_image()) {
|
|
|
+ if (!do_has_bam_rawdata()) {
|
|
|
gobj_cat.error()
|
|
|
<< get_name() << " does not have ram image\n";
|
|
|
return false;
|
|
|
@@ -5368,6 +5408,31 @@ do_reload() {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::do_has_bam_rawdata
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Returns true if there is a rawdata image that we have
|
|
|
+// available to write to the bam stream. For a normal
|
|
|
+// Texture, this is the same thing as
|
|
|
+// do_has_ram_image(), but a movie texture might define
|
|
|
+// it differently.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool Texture::
|
|
|
+do_has_bam_rawdata() const {
|
|
|
+ return do_has_ram_image();
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::do_get_bam_rawdata
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: If do_has_bam_rawdata() returned false, this attempts
|
|
|
+// to reload the rawdata image if possible.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Texture::
|
|
|
+do_get_bam_rawdata() {
|
|
|
+ do_get_ram_image();
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Texture::convert_from_pnmimage
|
|
|
// Access: Private, Static
|
|
|
@@ -6727,6 +6792,213 @@ register_with_read_factory() {
|
|
|
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
|
|
}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::write_datagram
|
|
|
+// Access: Public, Virtual
|
|
|
+// Description: Function to write the important information in
|
|
|
+// the particular object to a Datagram
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Texture::
|
|
|
+write_datagram(BamWriter *manager, Datagram &me) {
|
|
|
+ MutexHolder holder(_lock);
|
|
|
+
|
|
|
+ bool has_rawdata = false;
|
|
|
+ do_write_datagram_header(manager, me, has_rawdata);
|
|
|
+
|
|
|
+ do_write_datagram_body(manager, me);
|
|
|
+
|
|
|
+ // If we are also including the texture's image data, then stuff it
|
|
|
+ // in here.
|
|
|
+ if (has_rawdata) {
|
|
|
+ do_write_datagram_rawdata(manager, me);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::finalize
|
|
|
+// Access: Public, Virtual
|
|
|
+// Description: Called by the BamReader to perform any final actions
|
|
|
+// needed for setting up the object after all objects
|
|
|
+// have been read and all pointers have been completed.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Texture::
|
|
|
+finalize(BamReader *) {
|
|
|
+ // Unref the pointer that we explicitly reffed in make_from_bam().
|
|
|
+ unref();
|
|
|
+
|
|
|
+ // We should never get back to zero after unreffing our own count,
|
|
|
+ // because we expect to have been stored in a pointer somewhere. If
|
|
|
+ // we do get to zero, it's a memory leak; the way to avoid this is
|
|
|
+ // to call unref_delete() above instead of unref(), but this is
|
|
|
+ // dangerous to do from within a virtual function.
|
|
|
+ nassertv(get_ref_count() != 0);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::do_write_datagram_header
|
|
|
+// Access: Protected
|
|
|
+// Description: Writes the header part of the texture to the
|
|
|
+// Datagram. This is the common part that is shared by
|
|
|
+// all Texture subclasses, and contains the filename and
|
|
|
+// rawdata flags. This method is not virtual because
|
|
|
+// all Texture subclasses must write the same data at
|
|
|
+// this step.
|
|
|
+//
|
|
|
+// This part must be read first before calling
|
|
|
+// do_fillin_body() to determine whether to load the
|
|
|
+// Texture from the TexturePool or directly from the bam
|
|
|
+// stream.
|
|
|
+//
|
|
|
+// After this call, has_rawdata will be filled with
|
|
|
+// either true or false, according to whether we expect
|
|
|
+// to write the texture rawdata to the bam stream
|
|
|
+// following the texture body.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Texture::
|
|
|
+do_write_datagram_header(BamWriter *manager, Datagram &me, bool &has_rawdata) {
|
|
|
+ // Write out the texture's raw pixel data if (a) the current Bam
|
|
|
+ // Texture Mode requires that, or (b) there's no filename, so the
|
|
|
+ // file can't be loaded up from disk, but the raw pixel data is
|
|
|
+ // currently available in RAM.
|
|
|
+
|
|
|
+ // Otherwise, we just write out the filename, and assume whoever
|
|
|
+ // loads the bam file later will have access to the image file on
|
|
|
+ // disk.
|
|
|
+ BamWriter::BamTextureMode file_texture_mode = manager->get_file_texture_mode();
|
|
|
+ has_rawdata = (file_texture_mode == BamWriter::BTM_rawdata ||
|
|
|
+ (_filename.empty() && do_has_bam_rawdata()));
|
|
|
+ if (has_rawdata && !do_has_bam_rawdata()) {
|
|
|
+ do_get_bam_rawdata();
|
|
|
+ if (!do_has_bam_rawdata()) {
|
|
|
+ // No image data after all.
|
|
|
+ has_rawdata = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ bool has_bam_dir = !manager->get_filename().empty();
|
|
|
+ Filename bam_dir = manager->get_filename().get_dirname();
|
|
|
+ Filename filename = _filename;
|
|
|
+ Filename alpha_filename = _alpha_filename;
|
|
|
+
|
|
|
+ VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
|
|
+
|
|
|
+ switch (file_texture_mode) {
|
|
|
+ case BamWriter::BTM_unchanged:
|
|
|
+ case BamWriter::BTM_rawdata:
|
|
|
+ break;
|
|
|
+
|
|
|
+ case BamWriter::BTM_fullpath:
|
|
|
+ filename = _fullpath;
|
|
|
+ alpha_filename = _alpha_fullpath;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case BamWriter::BTM_relative:
|
|
|
+ filename = _fullpath;
|
|
|
+ alpha_filename = _alpha_fullpath;
|
|
|
+ bam_dir.make_absolute(vfs->get_cwd());
|
|
|
+ if (!has_bam_dir || !filename.make_relative_to(bam_dir, true)) {
|
|
|
+ filename.find_on_searchpath(get_model_path());
|
|
|
+ }
|
|
|
+ if (gobj_cat.is_debug()) {
|
|
|
+ gobj_cat.debug()
|
|
|
+ << "Texture file " << _fullpath
|
|
|
+ << " found as " << filename << "\n";
|
|
|
+ }
|
|
|
+ if (!has_bam_dir || !alpha_filename.make_relative_to(bam_dir, true)) {
|
|
|
+ alpha_filename.find_on_searchpath(get_model_path());
|
|
|
+ }
|
|
|
+ if (gobj_cat.is_debug()) {
|
|
|
+ gobj_cat.debug()
|
|
|
+ << "Alpha image " << _alpha_fullpath
|
|
|
+ << " found as " << alpha_filename << "\n";
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case BamWriter::BTM_basename:
|
|
|
+ filename = _fullpath.get_basename();
|
|
|
+ alpha_filename = _alpha_fullpath.get_basename();
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ gobj_cat.error()
|
|
|
+ << "Unsupported bam-texture-mode: " << (int)file_texture_mode << "\n";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (filename.empty() && do_has_bam_rawdata()) {
|
|
|
+ // If we don't have a filename, we have to store rawdata anyway.
|
|
|
+ has_rawdata = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ me.add_string(get_name());
|
|
|
+ me.add_string(filename);
|
|
|
+ me.add_string(alpha_filename);
|
|
|
+ me.add_uint8(_primary_file_num_channels);
|
|
|
+ me.add_uint8(_alpha_file_channel);
|
|
|
+ me.add_bool(has_rawdata);
|
|
|
+ me.add_uint8(_texture_type);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::do_write_datagram_body
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Writes the body part of the texture to the
|
|
|
+// Datagram. This is generally all of the texture
|
|
|
+// parameters except for the header and the rawdata.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Texture::
|
|
|
+do_write_datagram_body(BamWriter *manager, Datagram &me) {
|
|
|
+ me.add_uint8(_wrap_u);
|
|
|
+ me.add_uint8(_wrap_v);
|
|
|
+ me.add_uint8(_wrap_w);
|
|
|
+ me.add_uint8(_minfilter);
|
|
|
+ me.add_uint8(_magfilter);
|
|
|
+ me.add_int16(_anisotropic_degree);
|
|
|
+ _border_color.write_datagram(me);
|
|
|
+ me.add_uint8(_compression);
|
|
|
+ me.add_uint8(_quality_level);
|
|
|
+
|
|
|
+ me.add_uint8(_format);
|
|
|
+ me.add_uint8(_num_components);
|
|
|
+
|
|
|
+ me.add_uint32(_orig_file_x_size);
|
|
|
+ me.add_uint32(_orig_file_y_size);
|
|
|
+
|
|
|
+ bool has_simple_ram_image = !_simple_ram_image._image.empty();
|
|
|
+ me.add_bool(has_simple_ram_image);
|
|
|
+
|
|
|
+ // Write out the simple image too, so it will be available later.
|
|
|
+ if (has_simple_ram_image) {
|
|
|
+ me.add_uint32(_simple_x_size);
|
|
|
+ me.add_uint32(_simple_y_size);
|
|
|
+ me.add_int32(_simple_image_date_generated);
|
|
|
+ me.add_uint32(_simple_ram_image._image.size());
|
|
|
+ me.append_data(_simple_ram_image._image, _simple_ram_image._image.size());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::do_write_datagram_rawdata
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Writes the rawdata part of the texture to the
|
|
|
+// Datagram.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Texture::
|
|
|
+do_write_datagram_rawdata(BamWriter *manager, Datagram &me) {
|
|
|
+ me.add_uint32(_x_size);
|
|
|
+ me.add_uint32(_y_size);
|
|
|
+ me.add_uint32(_z_size);
|
|
|
+ me.add_uint8(_component_type);
|
|
|
+ me.add_uint8(_component_width);
|
|
|
+ me.add_uint8(_ram_image_compression);
|
|
|
+ me.add_uint8(_ram_images.size());
|
|
|
+ for (size_t n = 0; n < _ram_images.size(); ++n) {
|
|
|
+ me.add_uint32(_ram_images[n]._page_size);
|
|
|
+ me.add_uint32(_ram_images[n]._image.size());
|
|
|
+ me.append_data(_ram_images[n]._image, _ram_images[n]._image.size());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Texture::make_from_bam
|
|
|
// Access: Protected, Static
|
|
|
@@ -6734,18 +7006,35 @@ register_with_read_factory() {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
TypedWritable *Texture::
|
|
|
make_from_bam(const FactoryParams ¶ms) {
|
|
|
+ PT(Texture) dummy = new Texture;
|
|
|
+ return dummy->make_this_from_bam(params);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::make_this_from_bam
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Called by make_from_bam() once the particular
|
|
|
+// subclass of Texture is known. This is called on a
|
|
|
+// newly-constructed Texture object of the appropriate
|
|
|
+// subclass. It will return either the same Texture
|
|
|
+// object (e.g. this), or a different Texture object
|
|
|
+// loaded via the TexturePool, as appropriate.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+TypedWritable *Texture::
|
|
|
+make_this_from_bam(const FactoryParams ¶ms) {
|
|
|
// The process of making a texture is slightly different than making
|
|
|
// other TypedWritable objects. That is because all creation of
|
|
|
// Textures should be done through calls to TexturePool, which
|
|
|
// ensures that any loads of the same filename refer to the same
|
|
|
// memory.
|
|
|
+
|
|
|
DatagramIterator scan;
|
|
|
BamReader *manager;
|
|
|
|
|
|
parse_params(params, scan, manager);
|
|
|
|
|
|
- // Get the filenames and texture type so we can look up the file on
|
|
|
- // disk first.
|
|
|
+ // Get the header information--the filenames and texture type--so we
|
|
|
+ // can look up the file on disk first.
|
|
|
string name = scan.get_string();
|
|
|
Filename filename = scan.get_string();
|
|
|
Filename alpha_filename = scan.get_string();
|
|
|
@@ -6757,9 +7046,12 @@ make_from_bam(const FactoryParams ¶ms) {
|
|
|
|
|
|
Texture *me = NULL;
|
|
|
if (has_rawdata) {
|
|
|
- // If the raw image data is included, then just create a Texture
|
|
|
- // and don't load from the file.
|
|
|
- me = new Texture(name);
|
|
|
+ // If the raw image data is included, then just load the texture
|
|
|
+ // directly from the stream, and return it. In this case we
|
|
|
+ // return the "this" pointer, since it's a newly-created Texture
|
|
|
+ // object of the appropriate type.
|
|
|
+ me = this;
|
|
|
+ me->set_name(name);
|
|
|
me->_filename = filename;
|
|
|
me->_alpha_filename = alpha_filename;
|
|
|
me->_primary_file_num_channels = primary_file_num_channels;
|
|
|
@@ -6767,13 +7059,21 @@ make_from_bam(const FactoryParams ¶ms) {
|
|
|
me->_texture_type = texture_type;
|
|
|
|
|
|
// Read the texture attributes directly from the bam stream.
|
|
|
- me->fillin(scan, manager, has_rawdata);
|
|
|
+ me->do_fillin_body(scan, manager);
|
|
|
+ me->do_fillin_rawdata(scan, manager);
|
|
|
+
|
|
|
+ // To manage the reference count, explicitly ref it now, then
|
|
|
+ // unref it in the finalize callback.
|
|
|
+ me->ref();
|
|
|
+ manager->register_finalize(me);
|
|
|
|
|
|
} 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);
|
|
|
+ // The raw image data isn't included, so we'll be loading the
|
|
|
+ // Texture via the TexturePool. In this case we use the "this"
|
|
|
+ // pointer as a temporary object to read all of the attributes
|
|
|
+ // from the bam stream.
|
|
|
+ Texture *dummy = this;
|
|
|
+ dummy->do_fillin_body(scan, manager);
|
|
|
|
|
|
if (filename.empty()) {
|
|
|
// This texture has no filename; since we don't have an image to
|
|
|
@@ -6828,8 +7128,15 @@ make_from_bam(const FactoryParams ¶ms) {
|
|
|
}
|
|
|
|
|
|
if (me != (Texture *)NULL) {
|
|
|
- me->fillin_from(dummy);
|
|
|
+ {
|
|
|
+ MutexHolder holder(me->_lock);
|
|
|
+ me->do_fillin_from(dummy);
|
|
|
+ }
|
|
|
me->set_name(name);
|
|
|
+
|
|
|
+ // Since in this case me was loaded from the TexturePool,
|
|
|
+ // there's no need to explicitly manage the reference count.
|
|
|
+ // TexturePool will hold it safely.
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -6837,17 +7144,13 @@ make_from_bam(const FactoryParams ¶ms) {
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Texture::fillin
|
|
|
-// Access: Protected
|
|
|
-// Description: Function that reads out of the datagram (or asks
|
|
|
-// manager to read) all of the data that is needed to
|
|
|
-// re-create this object and stores it in the appropiate
|
|
|
-// place
|
|
|
+// Function: Texture::do_fillin_body
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Reads in the part of the Texture that was written
|
|
|
+// with do_write_datagram_body().
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void Texture::
|
|
|
-fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) {
|
|
|
- // We have already read in the filenames; don't read them again.
|
|
|
-
|
|
|
+do_fillin_body(DatagramIterator &scan, BamReader *manager) {
|
|
|
_wrap_u = (WrapMode)scan.get_uint8();
|
|
|
_wrap_v = (WrapMode)scan.get_uint8();
|
|
|
_wrap_w = (WrapMode)scan.get_uint8();
|
|
|
@@ -6890,59 +7193,64 @@ fillin(DatagramIterator &scan, BamReader *manager, bool has_rawdata) {
|
|
|
_simple_ram_image._page_size = u_size;
|
|
|
++_simple_image_modified;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- if (has_rawdata) {
|
|
|
- _x_size = scan.get_uint32();
|
|
|
- _y_size = scan.get_uint32();
|
|
|
- _z_size = scan.get_uint32();
|
|
|
- _component_type = (ComponentType)scan.get_uint8();
|
|
|
- _component_width = scan.get_uint8();
|
|
|
- _ram_image_compression = CM_off;
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Texture::do_fillin_rawdata
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Reads in the part of the Texture that was written
|
|
|
+// with do_write_datagram_rawdata().
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void Texture::
|
|
|
+do_fillin_rawdata(DatagramIterator &scan, BamReader *manager) {
|
|
|
+ _x_size = scan.get_uint32();
|
|
|
+ _y_size = scan.get_uint32();
|
|
|
+ _z_size = scan.get_uint32();
|
|
|
+ _component_type = (ComponentType)scan.get_uint8();
|
|
|
+ _component_width = scan.get_uint8();
|
|
|
+ _ram_image_compression = CM_off;
|
|
|
+ if (manager->get_file_minor_ver() >= 1) {
|
|
|
+ _ram_image_compression = (CompressionMode)scan.get_uint8();
|
|
|
+ }
|
|
|
+
|
|
|
+ int num_ram_images = 1;
|
|
|
+ if (manager->get_file_minor_ver() >= 3) {
|
|
|
+ num_ram_images = scan.get_uint8();
|
|
|
+ }
|
|
|
+
|
|
|
+ _ram_images.clear();
|
|
|
+ _ram_images.reserve(num_ram_images);
|
|
|
+ for (int n = 0; n < num_ram_images; ++n) {
|
|
|
+ _ram_images.push_back(RamImage());
|
|
|
+ _ram_images[n]._page_size = get_expected_ram_page_size();
|
|
|
if (manager->get_file_minor_ver() >= 1) {
|
|
|
- _ram_image_compression = (CompressionMode)scan.get_uint8();
|
|
|
- }
|
|
|
-
|
|
|
- int num_ram_images = 1;
|
|
|
- if (manager->get_file_minor_ver() >= 3) {
|
|
|
- num_ram_images = scan.get_uint8();
|
|
|
+ _ram_images[n]._page_size = scan.get_uint32();
|
|
|
}
|
|
|
-
|
|
|
- _ram_images.clear();
|
|
|
- _ram_images.reserve(num_ram_images);
|
|
|
- for (int n = 0; n < num_ram_images; ++n) {
|
|
|
- _ram_images.push_back(RamImage());
|
|
|
- _ram_images[n]._page_size = get_expected_ram_page_size();
|
|
|
- if (manager->get_file_minor_ver() >= 1) {
|
|
|
- _ram_images[n]._page_size = scan.get_uint32();
|
|
|
- }
|
|
|
-
|
|
|
- size_t u_size = scan.get_uint32();
|
|
|
-
|
|
|
- // fill the _image buffer with image data
|
|
|
- PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
|
|
|
- for (size_t u_idx = 0; u_idx < u_size; ++u_idx) {
|
|
|
- image[(int)u_idx] = scan.get_uint8();
|
|
|
- }
|
|
|
- _ram_images[n]._image = image;
|
|
|
+
|
|
|
+ size_t u_size = scan.get_uint32();
|
|
|
+
|
|
|
+ // fill the _image buffer with image data
|
|
|
+ PTA_uchar image = PTA_uchar::empty_array(u_size, get_class_type());
|
|
|
+ for (size_t u_idx = 0; u_idx < u_size; ++u_idx) {
|
|
|
+ image[(int)u_idx] = scan.get_uint8();
|
|
|
}
|
|
|
- _loaded_from_image = true;
|
|
|
- do_set_pad_size(0, 0, 0);
|
|
|
- ++_image_modified;
|
|
|
+ _ram_images[n]._image = image;
|
|
|
}
|
|
|
+ _loaded_from_image = true;
|
|
|
+ do_set_pad_size(0, 0, 0);
|
|
|
+ ++_image_modified;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Texture::fillin_from
|
|
|
-// Access: Protected
|
|
|
+// Function: Texture::do_fillin_from
|
|
|
+// Access: Protected, Virtual
|
|
|
// 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) {
|
|
|
- MutexHolder holder(_lock);
|
|
|
-
|
|
|
+do_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
|
|
|
@@ -6995,144 +7303,6 @@ fillin_from(Texture *dummy) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: Texture::write_datagram
|
|
|
-// Access: Public
|
|
|
-// Description: Function to write the important information in
|
|
|
-// the particular object to a Datagram
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void Texture::
|
|
|
-write_datagram(BamWriter *manager, Datagram &me) {
|
|
|
- MutexHolder holder(_lock);
|
|
|
-
|
|
|
- // Write out the texture's raw pixel data if (a) the current Bam
|
|
|
- // Texture Mode requires that, or (b) there's no filename, so the
|
|
|
- // file can't be loaded up from disk, but the raw pixel data is
|
|
|
- // currently available in RAM.
|
|
|
-
|
|
|
- // Otherwise, we just write out the filename, and assume whoever
|
|
|
- // loads the bam file later will have access to the image file on
|
|
|
- // disk.
|
|
|
- BamWriter::BamTextureMode file_texture_mode = manager->get_file_texture_mode();
|
|
|
- bool has_rawdata =
|
|
|
- (file_texture_mode == BamWriter::BTM_rawdata || (do_has_ram_image() && _filename.empty()));
|
|
|
- if (has_rawdata && !do_has_ram_image()) {
|
|
|
- do_get_ram_image();
|
|
|
- if (!do_has_ram_image()) {
|
|
|
- // No image data after all.
|
|
|
- has_rawdata = false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- bool has_bam_dir = !manager->get_filename().empty();
|
|
|
- Filename bam_dir = manager->get_filename().get_dirname();
|
|
|
- Filename filename = _filename;
|
|
|
- Filename alpha_filename = _alpha_filename;
|
|
|
-
|
|
|
- VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
|
|
-
|
|
|
- switch (file_texture_mode) {
|
|
|
- case BamWriter::BTM_unchanged:
|
|
|
- case BamWriter::BTM_rawdata:
|
|
|
- break;
|
|
|
-
|
|
|
- case BamWriter::BTM_fullpath:
|
|
|
- filename = _fullpath;
|
|
|
- alpha_filename = _alpha_fullpath;
|
|
|
- break;
|
|
|
-
|
|
|
- case BamWriter::BTM_relative:
|
|
|
- filename = _fullpath;
|
|
|
- alpha_filename = _alpha_fullpath;
|
|
|
- bam_dir.make_absolute(vfs->get_cwd());
|
|
|
- if (!has_bam_dir || !filename.make_relative_to(bam_dir, true)) {
|
|
|
- filename.find_on_searchpath(get_model_path());
|
|
|
- }
|
|
|
- if (gobj_cat.is_debug()) {
|
|
|
- gobj_cat.debug()
|
|
|
- << "Texture file " << _fullpath
|
|
|
- << " found as " << filename << "\n";
|
|
|
- }
|
|
|
- if (!has_bam_dir || !alpha_filename.make_relative_to(bam_dir, true)) {
|
|
|
- alpha_filename.find_on_searchpath(get_model_path());
|
|
|
- }
|
|
|
- if (gobj_cat.is_debug()) {
|
|
|
- gobj_cat.debug()
|
|
|
- << "Alpha image " << _alpha_fullpath
|
|
|
- << " found as " << alpha_filename << "\n";
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case BamWriter::BTM_basename:
|
|
|
- filename = _fullpath.get_basename();
|
|
|
- alpha_filename = _alpha_fullpath.get_basename();
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- gobj_cat.error()
|
|
|
- << "Unsupported bam-texture-mode: " << (int)file_texture_mode << "\n";
|
|
|
- }
|
|
|
-
|
|
|
- if (filename.empty() && do_has_ram_image()) {
|
|
|
- // If we don't have a filename, we have to store rawdata anyway.
|
|
|
- has_rawdata = true;
|
|
|
- }
|
|
|
-
|
|
|
- me.add_string(get_name());
|
|
|
- me.add_string(filename);
|
|
|
- me.add_string(alpha_filename);
|
|
|
- me.add_uint8(_primary_file_num_channels);
|
|
|
- me.add_uint8(_alpha_file_channel);
|
|
|
- me.add_bool(has_rawdata);
|
|
|
- me.add_uint8(_texture_type);
|
|
|
-
|
|
|
- // The data beginning at this point is handled by fillin().
|
|
|
- me.add_uint8(_wrap_u);
|
|
|
- me.add_uint8(_wrap_v);
|
|
|
- me.add_uint8(_wrap_w);
|
|
|
- me.add_uint8(_minfilter);
|
|
|
- me.add_uint8(_magfilter);
|
|
|
- me.add_int16(_anisotropic_degree);
|
|
|
- _border_color.write_datagram(me);
|
|
|
- me.add_uint8(_compression);
|
|
|
- me.add_uint8(_quality_level);
|
|
|
-
|
|
|
- me.add_uint8(_format);
|
|
|
- me.add_uint8(_num_components);
|
|
|
-
|
|
|
- me.add_uint32(_orig_file_x_size);
|
|
|
- me.add_uint32(_orig_file_y_size);
|
|
|
-
|
|
|
- bool has_simple_ram_image = !_simple_ram_image._image.empty();
|
|
|
- me.add_bool(has_simple_ram_image);
|
|
|
-
|
|
|
- // Write out the simple image too, so it will be available later.
|
|
|
- if (has_simple_ram_image) {
|
|
|
- me.add_uint32(_simple_x_size);
|
|
|
- me.add_uint32(_simple_y_size);
|
|
|
- me.add_int32(_simple_image_date_generated);
|
|
|
- me.add_uint32(_simple_ram_image._image.size());
|
|
|
- me.append_data(_simple_ram_image._image, _simple_ram_image._image.size());
|
|
|
- }
|
|
|
-
|
|
|
- // If we are also including the texture's image data, then stuff it
|
|
|
- // in here.
|
|
|
- if (has_rawdata) {
|
|
|
- me.add_uint32(_x_size);
|
|
|
- me.add_uint32(_y_size);
|
|
|
- me.add_uint32(_z_size);
|
|
|
- me.add_uint8(_component_type);
|
|
|
- me.add_uint8(_component_width);
|
|
|
- me.add_uint8(_ram_image_compression);
|
|
|
- me.add_uint8(_ram_images.size());
|
|
|
- for (size_t n = 0; n < _ram_images.size(); ++n) {
|
|
|
- me.add_uint32(_ram_images[n]._page_size);
|
|
|
- me.add_uint32(_ram_images[n]._image.size());
|
|
|
- me.append_data(_ram_images[n]._image, _ram_images[n]._image.size());
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: Texture::TextureType output operator
|
|
|
// Description:
|