summaryrefslogtreecommitdiffstats
path: root/o3d/import/cross/collada.cc
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-20 06:05:23 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-20 06:05:23 +0000
commite08b2652afb31bad466bc69d1f1aa3b80298361f (patch)
tree305527e71cd5d41394aab78e3607c9e8c31e7451 /o3d/import/cross/collada.cc
parentb2d346da57198822ddf59563a7c100eb6f6bc5a2 (diff)
downloadchromium_src-e08b2652afb31bad466bc69d1f1aa3b80298361f.zip
chromium_src-e08b2652afb31bad466bc69d1f1aa3b80298361f.tar.gz
chromium_src-e08b2652afb31bad466bc69d1f1aa3b80298361f.tar.bz2
Added --convert-dds-to-png command line option to the COLLADA converter,
which causes all DDS textures to be outputted as PNGs. This required changes to the serialization code to reconstitute cube map textures from six separate images. Some bugs in the plugin were uncovered with this change which have been worked around for the time being. Pulled in libtxc_dxtn library for decompressing DXTn textures. Tested by converting teapot with --convert-dds-to-png and running helloworld.html and render-mode.html. BUG=none TEST=none Review URL: http://codereview.chromium.org/1677002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45014 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/import/cross/collada.cc')
-rw-r--r--o3d/import/cross/collada.cc144
1 files changed, 143 insertions, 1 deletions
diff --git a/o3d/import/cross/collada.cc b/o3d/import/cross/collada.cc
index 2076921d..cfc64b3 100644
--- a/o3d/import/cross/collada.cc
+++ b/o3d/import/cross/collada.cc
@@ -56,7 +56,9 @@
#include "import/cross/collada_conditioner.h"
#include "import/cross/collada_zip_archive.h"
#include "import/cross/destination_buffer.h"
+#include "import/cross/file_output_stream_processor.h"
#include "utils/cross/file_path_utils.h"
+#include "third_party/libtxc_dxtn/files/txc_dxtn.h"
#define COLLADA_NAMESPACE "collada"
#define COLLADA_NAMESPACE_SEPARATOR "."
@@ -1698,7 +1700,147 @@ Texture* Collada::BuildTextureFromImage(FCDImage* image) {
tex->set_name(WideToUTF8(name.c_str()));
}
- if (options_.keep_original_data) {
+ bool inserted_original_data = false;
+ bool is_dds = uri.MatchesExtension(UTF8ToFilePathStringType(".dds"));
+
+ if (is_dds &&
+ options_.convert_dds_to_png &&
+ options_.keep_original_data) {
+ // The Texture stubs used by the converter don't have a working
+ // PlatformSpecificLock, so we need to reload the images using
+ // the Bitmap class. We also need to do the DXTn decompression
+ // on the CPU because D3D wouldn't provide access to the
+ // decompressed data anyway.
+
+ // These need to match the order of TextureCUBE::CubeFace.
+ static const char* cube_suffixes[6] = {
+ "_posx", "_negx", "_posy", "_negy", "_posz", "_negz"
+ };
+ static const char* cube_prefixes[6] = {
+ "posx_", "negx_", "posy_", "negy_", "posz_", "negz_"
+ };
+
+ BitmapRefArray bitmaps;
+ bool is_cube_map = false;
+ if (Bitmap::LoadFromFile(service_locator_, file_path,
+ image::UNKNOWN, &bitmaps)) {
+ is_cube_map = bitmaps.size() == 6;
+ for (unsigned int i = 0; i < bitmaps.size(); i++) {
+ bool is_compressed =
+ (tex->format() == Texture::DXT1 ||
+ tex->format() == Texture::DXT3 ||
+ tex->format() == Texture::DXT5);
+ Bitmap::Ref src_bitmap = bitmaps[i];
+ int pitch = src_bitmap->GetMipPitch(0);
+ if (is_compressed) {
+ // TODO(kbr): there is a bug somewhere in
+ // Bitmap::GetMipPitch for compressed textures where its
+ // result is off by a factor of two, at least for DXT1
+ // textures. Don't have time to debug it right now.
+ pitch /= 2;
+ }
+ uint8* data = src_bitmap->GetMipData(0);
+ int width = src_bitmap->width();
+ int height = src_bitmap->height();
+ int row_width = width * 4;
+ int decompressed_size = width * height * 4;
+ scoped_array<uint8> decompressed_data(new uint8[decompressed_size]);
+ memset(decompressed_data.get(), 0, decompressed_size);
+ if (is_compressed) {
+ for (int src_y = 0; src_y < height; src_y++) {
+ int dest_y = src_y;
+ if (is_cube_map) {
+ dest_y = height - src_y - 1;
+ }
+ for (int x = 0; x < width; x++) {
+ uint8* ptr =
+ &decompressed_data.get()[row_width * dest_y + 4 * x];
+ switch (src_bitmap->format()) {
+ case Texture::DXT1: {
+ fetch_2d_texel_rgba_dxt1(pitch, data, x, src_y, ptr);
+ break;
+ }
+ case Texture::DXT3: {
+ fetch_2d_texel_rgba_dxt3(pitch, data, x, src_y, ptr);
+ break;
+ }
+ case Texture::DXT5: {
+ fetch_2d_texel_rgba_dxt5(pitch, data, x, src_y, ptr);
+ break;
+ }
+ default:
+ DLOG(ERROR) << "Unsupported DDS compressed texture format "
+ << src_bitmap->format();
+ break;
+ }
+ // Need to swap the red and blue channels.
+ std::swap(ptr[0], ptr[2]);
+ }
+ }
+ } else if (src_bitmap->format() == Texture::XRGB8 ||
+ src_bitmap->format() == Texture::ARGB8) {
+ for (int src_y = 0; src_y < height; src_y++) {
+ int dest_y = src_y;
+ if (is_cube_map) {
+ dest_y = height - src_y - 1;
+ }
+ memcpy(decompressed_data.get() + row_width * dest_y,
+ data + pitch * src_y,
+ row_width);
+ }
+ } else {
+ DLOG(ERROR) << "Unsupported DDS uncompressed texture format "
+ << src_bitmap->format();
+ return NULL;
+ }
+ Bitmap::Ref bitmap(new Bitmap(service_locator_));
+ bitmap->Allocate(Texture::ARGB8,
+ width,
+ height,
+ 1,
+ Bitmap::IMAGE);
+ bitmap->SetRect(0, 0, 0, width, height,
+ decompressed_data.get(),
+ row_width);
+ std::vector<uint8> png_data;
+ if (!bitmap->WriteToPNGStream(&png_data)) {
+ DLOG(ERROR) << "Error writing PNG file for cube map";
+ }
+ FilePath png_uri = uri;
+ if (is_cube_map) {
+ png_uri = png_uri.InsertBeforeExtensionASCII(cube_suffixes[i]);
+ }
+ png_uri = png_uri.ReplaceExtension(UTF8ToFilePathStringType(".png"));
+ std::string contents;
+ contents.append(reinterpret_cast<char*>(&png_data.front()),
+ png_data.size());
+ original_data_map_.AddData(png_uri, contents, service_locator_);
+ inserted_original_data = true;
+
+ // We need to rewrite the o3d.uri param in the Texture as
+ // well. For cube map textures, we insert six params named
+ // "o3d.negx_uri", etc. and remove the "o3d.uri" param.
+ ParamString* uri_param = NULL;
+ if (is_cube_map) {
+ String name(O3D_STRING_CONSTANT(""));
+ name = name.append(cube_prefixes[i]).append("uri");
+ uri_param = tex->CreateParam<ParamString>(name);
+ } else {
+ uri_param = tex->GetParam<ParamString>(O3D_STRING_CONSTANT("uri"));
+ }
+ DCHECK(uri_param != NULL);
+ uri_param->set_value(FilePathToUTF8(png_uri));
+ }
+ }
+ if (is_cube_map) {
+ ParamString* uri_param =
+ tex->GetParam<ParamString>(O3D_STRING_CONSTANT("uri"));
+ DCHECK(uri_param != NULL);
+ tex->RemoveParam(uri_param);
+ }
+ }
+
+ if (options_.keep_original_data && !inserted_original_data) {
// Cache the original data by URI so we can recover it later.
std::string contents;
file_util::ReadFileToString(file_path, &contents);