Browse Source

Tweaks and switching to lib squish API

Josh Engebretson 9 years ago
parent
commit
159f03c8fb

+ 65 - 56
Source/Atomic/Resource/Image.cpp

@@ -36,6 +36,10 @@
 
 #include "../DebugNew.h"
 
+#ifdef ATOMIC_PLATFORM_DESKTOP
+#include <libsquish/squish.h>
+#endif
+
 extern "C" unsigned char* stbi_write_png_to_mem(unsigned char* pixels, int stride_bytes, int x, int y, int n, int* out_len);
 
 #ifndef MAKEFOURCC
@@ -1213,7 +1217,12 @@ bool Image::SaveJPG(const String& fileName, int quality) const
 
 bool Image::SaveDDS(const String& fileName) const
 {
-#if defined(ATOMIC_PLATFORM_WINDOWS) || defined (ATOMIC_PLATFORM_LINUX) || defined (ATOMIC_PLATFORM_OSX)
+#if !defined(ATOMIC_PLATFORM_DESKTOP)
+
+    LOGERRORF("Image::SaveDDS - Unsupported on current platform: %s", fileName.CString());
+    return false;
+
+#else
     PROFILE(SaveImageDDS);
 
     FileSystem* fileSystem = GetSubsystem<FileSystem>();
@@ -1235,68 +1244,73 @@ bool Image::SaveDDS(const String& fileName) const
         // with subclasses for particular image output types. Also should have image settings in the image meta.
         // ImageReader/Writers should also support a progress callback so UI can be updated.
 
-#ifdef CRUNCH
-        // Compression setup
-        crn_comp_params compParams;
-        compParams.m_width = width_;
-        compParams.m_height = height_;
-        compParams.set_flag(cCRNCompFlagPerceptual, true); // IsSRGB() incorrectly returning false
-        compParams.set_flag(cCRNCompFlagDXT1AForTransparency, false);
-        compParams.set_flag(cCRNCompFlagHierarchical, true);
-        compParams.m_file_type = cCRNFileTypeDDS;
-        compParams.m_format = (HasAlphaChannel() ? cCRNFmtDXT5 : cCRNFmtDXT1);
-
-        compParams.m_pImages[0][0] = (uint32_t*)data_.Get();
-
-        compParams.m_target_bitrate = 0;
-        compParams.m_quality_level = 255;
-        compParams.m_num_helper_threads = 1;
-        compParams.m_pProgress_func = nullptr;
-
-        // Mipmap setup
-        crn_mipmap_params mipParams;
-        mipParams.m_gamma_filtering = true; // IsSRGB() incorrectly returns false
-        mipParams.m_mode = cCRNMipModeNoMips; // or cCRNMipModeGenerateMips
-
-        // Output params
-        crn_uint32 actualQualityLevel;
-        float actualBitrate;
-        crn_uint32 outputFileSize;
-
-        void* compressedData = crn_compress(
-            compParams, 
-            mipParams, 
-            outputFileSize, 
-            &actualQualityLevel, 
-            &actualBitrate);
-
-        if (nullptr == compressedData)
+        if (!width_ || !height_)
+        {
+            LOGERRORF("Attempting to save zero width/height DDS to %s", fileName.CString());
+            return false;
+        }
+
+
+        squish::u8 *inputData = (squish::u8 *) data_.Get();
+
+        SharedPtr<Image> tempImage;
+
+        // libsquish expects 4 channel RGBA, so create a temporary image if necessary
+        if (components_ != 4)
+        {
+            if (components_ != 3)
+            {
+                LOGERROR("Can only save images with 3 or 4 components to DDS");
+                return false;
+            }
+
+            tempImage = new Image(context_);
+            tempImage->SetSize(width_, height_, 4);
+
+            squish::u8* srcBits = (squish::u8*) data_;
+            squish::u8* dstBits = (squish::u8*) tempImage->data_;
+
+            for (unsigned i = 0; i < width_ * height_ * 4; i++)
+            {
+                *dstBits++ = *srcBits++;
+                *dstBits++ = *srcBits++;
+                *dstBits++ = *srcBits++;
+                *dstBits++ = 255;
+            }
+
+            inputData = (squish::u8 *) tempImage->data_.Get();
+        }
+
+
+        unsigned storageRequirements = (unsigned) squish::GetStorageRequirements( width_, height_, HasAlphaChannel() ? squish::kDxt5 : squish::kDxt1 );
+        SharedArrayPtr<unsigned char> compressedData(new unsigned char[storageRequirements]);
+
+        squish::CompressImage(inputData, width_, height_, compressedData.Get(), HasAlphaChannel() ? squish::kDxt5 : squish::kDxt1);
+
+        if (compressedData)
         {
             LOGERROR("Failed to compress image to DXT");
             return false;
         }
 
-        FileSystem* fileSystem = GetSubsystem<FileSystem>();
         SharedPtr<File> dest(new File(context_, fileName, FILE_WRITE));
 
-        if (dest.Null())
+        if (!dest->IsOpen())
         {
-            // Open error already logged
-            crn_free_block(compressedData);
+            LOGERRORF("Failed to open DXT image file for writing %s", fileName.CString());
             return false;
         }
         else
         {
-            bool success = dest->Write(compressedData, outputFileSize) == outputFileSize;
-            crn_free_block(compressedData);
+            bool success = dest->Write(compressedData.Get(), storageRequirements) == storageRequirements;
+
+            if (!success)
+                LOGERRORF("Failed to write image to DXT, file size mismatch %s", fileName.CString());
+
             return success;
-        }
-#endif
-        
+        }        
         // #623 END TODO
-    }
-#else
-    LOGWARNING("Image::SaveDDS - Unsupported on current platform");
+    }    
 #endif
 
     return false;
@@ -2135,13 +2149,8 @@ unsigned char* Image::GetImageData(Deserializer& source, int& width, int& height
 
     SharedArrayPtr<unsigned char> buffer(new unsigned char[dataSize]);
     source.Read(buffer.Get(), dataSize);
-    // #623 BEGIN TODO: Crunch expects all 4 components. This isn't ideal, but since
-    // precompressed versions should always be loaded anyway it doesn't matter.
-    // Might need to handle differently per platform.
-        components = 4;
-        return stbi_load_from_memory(buffer.Get(), dataSize, &width, &height, nullptr, components);
-    // #623 END TODO: Crunch expects all 4 components. This isn't ideal, but since
-    }
+    return stbi_load_from_memory(buffer.Get(), dataSize, &width, &height, (int*)&components, 0);
+}
 
 void Image::FreeImageData(unsigned char* pixelData)
 {

+ 1 - 1
Source/Atomic/Resource/ResourceCache.cpp

@@ -599,7 +599,7 @@ Resource* ResourceCache::GetResource(StringHash type, const String& nameIn, bool
 
     // #623 BEGIN TODO: For now try to get DDS version of textures from /DDS cache sub directory,
     // ultimately should have per platform compressed versions saved in cache
-#if ATOMIC_PLATFORM_WINDOWS
+#ifdef ATOMIC_PLATFORM_DESKTOP
     String ext = Atomic::GetExtension(name);
     if (ext == ".jpg" || ext == ".png" || ext == ".tga")
     {

+ 2 - 10
Source/ToolCore/Assets/TextureImporter.cpp

@@ -57,30 +57,22 @@ bool TextureImporter::Import()
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     String cachePath = db->GetCachePath();
 
-    // #623 BEGIN TODO: Delete previously saved per-platform compressed version so
-    // it won't get re-loaded here
-#if ATOMIC_PLATFORM_WINDOWS
     FileSystem* fileSystem = GetSubsystem<FileSystem>();
     String compressedPath = cachePath + "DDS/" + asset_->GetRelativePath() + ".dds";
-    fileSystem->Delete(compressedPath);
-#endif
-    // #623 END TODO
+    if (fileSystem->FileExists(compressedPath))
+        fileSystem->Delete(compressedPath);
 
     SharedPtr<Image> image = cache->GetTempResource<Image>(asset_->GetPath());
 
     if (image.Null())
         return false;
 
-    // #623 BEGIN TODO: Save per-platform compressed version to cache
-#if ATOMIC_PLATFORM_WINDOWS
     if (compressTextures_ &&
         !image->IsCompressed())
     {
         fileSystem->CreateDirs(cachePath, "DDS/" + Atomic::GetPath(asset_->GetRelativePath()));
         image->SaveDDS(compressedPath);
     }
-#endif
-    // #623 END TODO
 
     // todo, proper proportions
     image->Resize(64, 64);

+ 23 - 0
Source/ToolCore/Build/BuildMac.cpp

@@ -26,6 +26,7 @@
 #include "../ToolSystem.h"
 #include "../ToolEnvironment.h"
 #include "../Project/Project.h"
+#include "../Assets/AssetDatabase.h"
 
 #include "BuildEvents.h"
 #include "BuildSystem.h"
@@ -67,6 +68,28 @@ void BuildMac::Initialize()
 
 }
 
+bool BuildMac::CheckIncludeResourceFile(const String& resourceDir, const String& fileName)
+{
+    // #623 BEGIN TODO: Skip files that have a converted version in the cache
+    AssetDatabase* db = GetSubsystem<AssetDatabase>();
+    String cachePath = db->GetCachePath();
+    if (resourceDir != cachePath)
+    {
+        String ext = GetExtension(fileName);
+        if (ext == ".jpg" || ext == ".png" || ext == ".tga")
+        {
+            FileSystem* fileSystem = GetSubsystem<FileSystem>();
+            String compressedPath = cachePath + "DDS/" + fileName + ".dds";
+            if (fileSystem->FileExists(compressedPath))
+                return false;
+        }
+    }
+    // #623 END TODO
+
+    return BuildBase::CheckIncludeResourceFile(resourceDir, fileName);
+}
+
+
 void BuildMac::Build(const String& buildPath)
 {
     ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();

+ 1 - 0
Source/ToolCore/Build/BuildMac.h

@@ -45,6 +45,7 @@ public:
 protected:
 
     void Initialize();
+    virtual bool CheckIncludeResourceFile(const String& resourceDir, const String& fileName);
 
 
 };