// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. #include "Core.h" #include "ModuleInterface.h" #include "ModuleManager.h" #include "TargetPlatform.h" #include "TextureCompressorModule.h" #include "PixelFormat.h" #include "ImageCore.h" DEFINE_LOG_CATEGORY_STATIC(LogTextureFormatUncompressed, Log, All); /** * Macro trickery for supported format names. */ #define ENUM_SUPPORTED_FORMATS(op) \ op(BGRA8) \ op(G8) \ op(VU8) \ op(RGBA16F) \ op(XGXR8) \ op(RGBA8) #define DECL_FORMAT_NAME(FormatName) static FName GTextureFormatName##FormatName = FName(TEXT(#FormatName)); ENUM_SUPPORTED_FORMATS(DECL_FORMAT_NAME); #undef DECL_FORMAT_NAME #define DECL_FORMAT_NAME_ENTRY(FormatName) GTextureFormatName##FormatName , static FName GSupportedTextureFormatNames[] = { ENUM_SUPPORTED_FORMATS(DECL_FORMAT_NAME_ENTRY) }; #undef DECL_FORMAT_NAME_ENTRY #undef ENUM_SUPPORTED_FORMATS /** * Uncompressed texture format handler. */ class FTextureFormatUncompressed : public ITextureFormat { virtual bool AllowParallelBuild() const OVERRIDE { return true; } virtual uint16 GetVersion(FName Format) const OVERRIDE { return 0; } virtual void GetSupportedFormats(TArray& OutFormats) const OVERRIDE { for (int32 i = 0; i < ARRAY_COUNT(GSupportedTextureFormatNames); ++i) { OutFormats.Add(GSupportedTextureFormatNames[i]); } } virtual FTextureFormatCompressorCaps GetFormatCapabilities() const OVERRIDE { return FTextureFormatCompressorCaps(); // Default capabilities. } virtual bool CompressImage( const FImage& InImage, const struct FTextureBuildSettings& BuildSettings, bool bImageHasAlphaChannel, FCompressedImage2D& OutCompressedImage ) const OVERRIDE { if (BuildSettings.TextureFormatName == GTextureFormatNameG8) { FImage Image; InImage.CopyTo(Image, ERawImageFormat::G8, BuildSettings.bSRGB); OutCompressedImage.SizeX = Image.SizeX; OutCompressedImage.SizeY = Image.SizeY; OutCompressedImage.PixelFormat = PF_G8; OutCompressedImage.RawData = Image.RawData; return true; } else if (BuildSettings.TextureFormatName == GTextureFormatNameVU8) { FImage Image; InImage.CopyTo(Image, ERawImageFormat::BGRA8, BuildSettings.bSRGB); OutCompressedImage.SizeX = Image.SizeX; OutCompressedImage.SizeY = Image.SizeY; OutCompressedImage.PixelFormat = PF_V8U8; uint32 NumTexels = Image.SizeX * Image.SizeY * Image.NumSlices; OutCompressedImage.RawData.Empty(NumTexels * 2); OutCompressedImage.RawData.AddUninitialized(NumTexels * 2); const FColor* FirstColor = Image.AsBGRA8(); const FColor* LastColor = FirstColor + NumTexels; int8* Dest = (int8*)OutCompressedImage.RawData.GetTypedData(); for (const FColor* Color = FirstColor; Color < LastColor; ++Color) { *Dest++ = (int32)Color->R - 128; *Dest++ = (int32)Color->G - 128; } return true; } else if (BuildSettings.TextureFormatName == GTextureFormatNameBGRA8) { FImage Image; InImage.CopyTo(Image, ERawImageFormat::BGRA8, BuildSettings.bSRGB); OutCompressedImage.SizeX = Image.SizeX; OutCompressedImage.SizeY = Image.SizeY; OutCompressedImage.PixelFormat = PF_B8G8R8A8; OutCompressedImage.RawData = Image.RawData; return true; } else if (BuildSettings.TextureFormatName == GTextureFormatNameRGBA8) { FImage Image; InImage.CopyTo(Image, ERawImageFormat::BGRA8, BuildSettings.bSRGB); OutCompressedImage.SizeX = Image.SizeX; OutCompressedImage.SizeY = Image.SizeY; OutCompressedImage.PixelFormat = PF_B8G8R8A8; // swizzle each texel uint32 NumTexels = Image.SizeX * Image.SizeY * Image.NumSlices; OutCompressedImage.RawData.Empty(NumTexels * 4); OutCompressedImage.RawData.AddUninitialized(NumTexels * 4); const FColor* FirstColor = Image.AsBGRA8(); const FColor* LastColor = FirstColor + NumTexels; int8* Dest = (int8*)OutCompressedImage.RawData.GetTypedData(); for (const FColor* Color = FirstColor; Color < LastColor; ++Color) { *Dest++ = (int32)Color->R; *Dest++ = (int32)Color->G; *Dest++ = (int32)Color->B; *Dest++ = (int32)Color->A; } return true; } else if (BuildSettings.TextureFormatName == GTextureFormatNameXGXR8) { FImage Image; InImage.CopyTo(Image, ERawImageFormat::BGRA8, BuildSettings.bSRGB); OutCompressedImage.SizeX = Image.SizeX; OutCompressedImage.SizeY = Image.SizeY; OutCompressedImage.PixelFormat = PF_B8G8R8A8; // swizzle each texel uint32 NumTexels = Image.SizeX * Image.SizeY * Image.NumSlices; OutCompressedImage.RawData.Empty(NumTexels * 4); OutCompressedImage.RawData.AddUninitialized(NumTexels * 4); const FColor* FirstColor = Image.AsBGRA8(); const FColor* LastColor = FirstColor + NumTexels; int8* Dest = (int8*)OutCompressedImage.RawData.GetTypedData(); for (const FColor* Color = FirstColor; Color < LastColor; ++Color) { *Dest++ = (int32)Color->B; *Dest++ = (int32)Color->G; *Dest++ = (int32)Color->A; *Dest++ = (int32)Color->R; } return true; } else if (BuildSettings.TextureFormatName == GTextureFormatNameRGBA16F) { FImage Image; InImage.CopyTo(Image, ERawImageFormat::RGBA16F, false); OutCompressedImage.SizeX = Image.SizeX; OutCompressedImage.SizeY = Image.SizeY; OutCompressedImage.PixelFormat = PF_FloatRGBA; OutCompressedImage.RawData = Image.RawData; return true; } UE_LOG(LogTextureFormatUncompressed, Warning, TEXT("Cannot convert uncompressed image to format '%s'."), *BuildSettings.TextureFormatName.ToString() ); return false; } }; /** * Module for uncompressed texture formats. */ static ITextureFormat* Singleton = NULL; class FTextureFormatUncompressedModule : public ITextureFormatModule { public: virtual ~FTextureFormatUncompressedModule() { delete Singleton; Singleton = NULL; } virtual ITextureFormat* GetTextureFormat() { if (!Singleton) { Singleton = new FTextureFormatUncompressed(); } return Singleton; } }; IMPLEMENT_MODULE(FTextureFormatUncompressedModule, TextureFormatUncompressed);