diff options
-rw-r--r-- | guilib/DirectXGraphics.cpp | 6 | ||||
-rw-r--r-- | guilib/GUIFontTTFDX.cpp | 6 | ||||
-rw-r--r-- | guilib/GUIFontTTFGL.cpp | 20 | ||||
-rw-r--r-- | guilib/Texture.cpp | 205 | ||||
-rw-r--r-- | guilib/Texture.h | 39 | ||||
-rw-r--r-- | guilib/TextureBundleXBT.cpp | 101 | ||||
-rw-r--r-- | guilib/TextureBundleXBT.h | 3 | ||||
-rw-r--r-- | guilib/TextureDX.cpp | 72 | ||||
-rw-r--r-- | guilib/TextureDX.h | 2 | ||||
-rw-r--r-- | guilib/TextureGL.cpp | 58 | ||||
-rw-r--r-- | guilib/TextureGL.h | 4 | ||||
-rw-r--r-- | guilib/TextureManager.cpp | 2 | ||||
-rw-r--r-- | guilib/XBTF.cpp | 63 | ||||
-rw-r--r-- | guilib/XBTF.h | 43 | ||||
-rw-r--r-- | guilib/XBTFReader.cpp | 19 | ||||
-rw-r--r-- | guilib/XBTFReader.h | 6 | ||||
-rw-r--r-- | tools/XBMCTexXBT/Win32/TexturePacker.vcproj | 2 | ||||
-rw-r--r-- | tools/XBMCTexXBT/XBMCTex.cpp | 300 | ||||
-rw-r--r-- | tools/XBMCTexXBT/XBTFWriter.cpp | 38 | ||||
-rw-r--r-- | tools/XBMCTexXBT/XBTFWriter.h | 4 | ||||
-rw-r--r-- | xbmc/GUIDialogTeletext.cpp | 4 | ||||
-rw-r--r-- | xbmc/Picture.cpp | 2 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/WinRenderer.cpp | 2 | ||||
-rw-r--r-- | xbmc/karaoke/karaokelyricscdg.cpp | 2 |
24 files changed, 532 insertions, 471 deletions
diff --git a/guilib/DirectXGraphics.cpp b/guilib/DirectXGraphics.cpp index 3a3d107c46..697742182a 100644 --- a/guilib/DirectXGraphics.cpp +++ b/guilib/DirectXGraphics.cpp @@ -395,7 +395,7 @@ void GetTextureFromData(D3DTexture *pTex, void *texData, CBaseTexture **ppTextur DWORD width, height, pitch, offset; ParseTextureHeader(pTex, fmt, width, height, pitch, offset); - *ppTexture = new CTexture(width, height, 32, XB_FMT_B8G8R8A8); + *ppTexture = new CTexture(width, height, XB_FMT_A8R8G8B8); if (*ppTexture) { @@ -447,9 +447,9 @@ void GetTextureFromData(D3DTexture *pTex, void *texData, CBaseTexture **ppTextur } if (IsPalettedFormat(fmt)) - (*ppTexture)->LoadPaletted(width, height, pitch, XB_FMT_B8G8R8A8, texDataStart, color); + (*ppTexture)->LoadPaletted(width, height, pitch, XB_FMT_A8R8G8B8, texDataStart, color); else - (*ppTexture)->LoadFromMemory(width, height, pitch, 32, XB_FMT_B8G8R8A8, texDataStart); + (*ppTexture)->LoadFromMemory(width, height, pitch, XB_FMT_A8R8G8B8, texDataStart); if (IsSwizzledFormat(fmt) || fmt == XB_D3DFMT_DXT1 || fmt == XB_D3DFMT_DXT2 || fmt == XB_D3DFMT_DXT4) { diff --git a/guilib/GUIFontTTFDX.cpp b/guilib/GUIFontTTFDX.cpp index 31cd79fbf7..64a8a05ca9 100644 --- a/guilib/GUIFontTTFDX.cpp +++ b/guilib/GUIFontTTFDX.cpp @@ -122,16 +122,16 @@ void CGUIFontTTFDX::End() CBaseTexture* CGUIFontTTFDX::ReallocTexture(unsigned int& newHeight)
{
- CBaseTexture* pNewTexture = new CTexture(m_textureWidth, newHeight, 8, XB_FMT_A8);
+ CBaseTexture* pNewTexture = new CTexture(m_textureWidth, newHeight, XB_FMT_A8);
- if(pNewTexture == NULL)
+ if (pNewTexture == NULL)
return NULL;
pNewTexture->CreateTextureObject();
LPDIRECT3DTEXTURE9 newTexture = pNewTexture->GetTextureObject();
- if(newTexture == NULL)
+ if (newTexture == NULL)
return NULL;
// correct texture sizes
diff --git a/guilib/GUIFontTTFGL.cpp b/guilib/GUIFontTTFGL.cpp index 7472bafba1..2a358436a8 100644 --- a/guilib/GUIFontTTFGL.cpp +++ b/guilib/GUIFontTTFGL.cpp @@ -46,12 +46,10 @@ using namespace std; CGUIFontTTFGL::CGUIFontTTFGL(const CStdString& strFileName) : CGUIFontTTFBase(strFileName) { - } CGUIFontTTFGL::~CGUIFontTTFGL(void) { - } void CGUIFontTTFGL::Begin() @@ -126,20 +124,8 @@ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight) { newHeight = CBaseTexture::PadPow2(newHeight); - CBaseTexture* newTexture = new CTexture(m_textureWidth, newHeight, 8); -/* yuvalt + CBaseTexture* newTexture = new CTexture(m_textureWidth, newHeight, XB_FMT_A8); -#ifdef __APPLE__ - // Because of an SDL bug (?), bpp gets set to 4 even though we asked for 1, in fullscreen mode. - // To be completely honest, we probably shouldn't even be using an SDL surface in OpenGL mode, since - // we only use it to store the image before copying it (no blitting!) to an OpenGL texture. - // - if (newTexture->GetPitch() != m_textureWidth) - newTexture->SetPitch(m_textureWidth); -#endif - -*/ - if (!newTexture || newTexture->GetPixels() == NULL) { CLog::Log(LOGERROR, "GUIFontTTFGL::CacheCharacter: Error creating new cache texture for size %f", m_height); @@ -166,8 +152,6 @@ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight) bool CGUIFontTTFGL::CopyCharToTexture(FT_BitmapGlyph bitGlyph, Character* ch) { - //SDL_LockSurface(m_texture); - FT_Bitmap bitmap = bitGlyph->bitmap; unsigned char* source = (unsigned char*) bitmap.buffer; @@ -191,8 +175,6 @@ bool CGUIFontTTFGL::CopyCharToTexture(FT_BitmapGlyph bitGlyph, Character* ch) m_bTextureLoaded = false; } - //SDL_UnlockSurface(m_texture); - return TRUE; } diff --git a/guilib/Texture.cpp b/guilib/Texture.cpp index 787d19b6c6..1b1a4bfde9 100644 --- a/guilib/Texture.cpp +++ b/guilib/Texture.cpp @@ -30,103 +30,106 @@ /************************************************************************/ /* */ /************************************************************************/ -CBaseTexture::CBaseTexture(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format) +CBaseTexture::CBaseTexture(unsigned int width, unsigned int height, unsigned int format) { - m_imageWidth = width; - m_imageHeight = height; - m_pTexture = NULL; - m_pPixels = NULL; - m_nBPP = BPP; + m_texture = NULL; + m_pixels = NULL; m_loadedToGPU = false; - m_nTextureHeight = 0; - m_nTextureWidth = 0; - m_format = format; + Allocate(width, height, format); } CBaseTexture::~CBaseTexture() { - delete[] m_pPixels; + delete[] m_pixels; } -void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format) +void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned int format) { - if (BPP != 0) - m_nBPP = BPP; - m_imageWidth = width; m_imageHeight = height; m_format = format; - if (g_Windowing.NeedPower2Texture()) + if (!g_Windowing.SupportsNPOT((m_format & XB_FMT_DXT_MASK) != 0)) { - m_nTextureWidth = PadPow2(m_imageWidth); - m_nTextureHeight = PadPow2(m_imageHeight); + m_textureWidth = PadPow2(m_imageWidth); + m_textureHeight = PadPow2(m_imageHeight); } else { - m_nTextureWidth = m_imageWidth; - m_nTextureHeight = m_imageHeight; + m_textureWidth = m_imageWidth; + m_textureHeight = m_imageHeight; } - - delete[] m_pPixels; - - switch (m_format) - { - case XB_FMT_DXT1: - m_bufferSize = ((m_imageWidth + 3) / 4) * ((m_imageHeight + 3) / 4) * 8; - break; - case XB_FMT_DXT3: - case XB_FMT_DXT5: - m_bufferSize = ((m_imageWidth + 3) / 4) * ((m_imageHeight + 3) / 4) * 16; - break; - default: - m_bufferSize = m_nTextureWidth * m_nTextureHeight * m_nBPP / 8; - break; + if (m_format & XB_FMT_DXT_MASK) + { // DXT textures must be a multiple of 4 in width and height + m_textureWidth = ((m_textureWidth + 3) / 4) * 4; + m_textureHeight = ((m_textureHeight + 3) / 4) * 4; } - - m_pPixels = new unsigned char[m_bufferSize]; + + delete[] m_pixels; + m_pixels = new unsigned char[GetPitch() * GetRows()]; } -void CBaseTexture::Update(int w, int h, int pitch, unsigned int format, const unsigned char *pixels, bool loadToGPU) +void CBaseTexture::Update(unsigned int width, unsigned int height, unsigned int pitch, unsigned int format, const unsigned char *pixels, bool loadToGPU) { if (pixels == NULL) return; - Allocate(w, h, 0, format); + Allocate(width, height, format); + + unsigned int srcPitch = pitch ? pitch : GetPitch(width); + unsigned int srcRows = GetRows(height); + unsigned int dstPitch = GetPitch(m_textureWidth); + unsigned int dstRows = GetRows(m_textureHeight); + + assert(srcPitch <= dstPitch && srcRows <= dstRows); - if (m_imageHeight != m_nTextureHeight || m_imageWidth != m_nTextureWidth) + if (srcPitch == dstPitch) + memcpy(m_pixels, pixels, srcPitch * srcRows); + else { - // Resize texture to POT if needed const unsigned char *src = pixels; - unsigned char* resized = m_pPixels; - - for (int y = 0; y < h; y++) + unsigned char* dst = m_pixels; + for (unsigned int y = 0; y < srcRows; y++) { - memcpy(resized, src, pitch); // make sure pitch is not bigger than our width - src += pitch; - - // repeat last column to simulate clamp_to_edge - for(unsigned int i = pitch; i < m_nTextureWidth*4; i+=4) - memcpy(resized+i, src-4, 4); - - resized += (m_nTextureWidth * 4); + memcpy(dst, src, srcPitch); + src += srcPitch; + dst += dstPitch; } - - // clamp to edge - repeat last row - unsigned char *dest = m_pPixels + h*GetPitch(); - for (unsigned int y = h; y < m_nTextureHeight; y++) + } + ClampToEdge(); + + if (loadToGPU) + LoadToGPU(); +} + +void CBaseTexture::ClampToEdge() +{ + unsigned int imagePitch = GetPitch(m_imageWidth); + unsigned int imageRows = GetRows(m_imageHeight); + unsigned int texturePitch = GetPitch(m_textureWidth); + unsigned int textureRows = GetRows(m_textureHeight); + if (imagePitch < texturePitch) + { + unsigned int blockSize = GetBlockSize(); + unsigned char *src = m_pixels + imagePitch - blockSize; + unsigned char *dst = m_pixels; + for (unsigned int y = 0; y < imageRows; y++) { - memcpy(dest, dest-GetPitch(), GetPitch()); - dest += GetPitch(); + for (unsigned int x = imagePitch; x < texturePitch; x += blockSize) + memcpy(dst + x, src, blockSize); + dst += texturePitch; } } - else + + if (imageRows < textureRows) { - memcpy(m_pPixels, pixels, m_bufferSize); + unsigned char *dst = m_pixels + imageRows * texturePitch; + for (unsigned int y = imageRows; y < textureRows; y++) + { + memcpy(dst, dst - texturePitch, texturePitch); + dst += texturePitch; + } } - - if (loadToGPU) - LoadToGPU(); } bool CBaseTexture::LoadFromFile(const CStdString& texturePath) @@ -137,17 +140,16 @@ bool CBaseTexture::LoadFromFile(const CStdString& texturePath) CLog::Log(LOGERROR, "Texture manager unable to load file: %s", texturePath.c_str()); return false; } + ClampToEdge(); return true; } -bool CBaseTexture::LoadFromMemory(unsigned int width, unsigned int height, unsigned int pitch, unsigned int BPP, unsigned int format, unsigned char* pPixels) +bool CBaseTexture::LoadFromMemory(unsigned int width, unsigned int height, unsigned int pitch, unsigned int format, unsigned char* pixels) { m_imageWidth = width; m_imageHeight = height; - m_nBPP = BPP; m_format = format; - Update(width, height, pitch, format, pPixels, false); - + Update(width, height, pitch, format, pixels, false); return true; } @@ -156,11 +158,11 @@ bool CBaseTexture::LoadPaletted(unsigned int width, unsigned int height, unsigne if (pixels == NULL || palette == NULL) return false; - Allocate(width, height, 32, format); + Allocate(width, height, format); for (unsigned int y = 0; y < height; y++) { - unsigned char *dest = m_pPixels + y * GetPitch(); + unsigned char *dest = m_pixels + y * GetPitch(); const unsigned char *src = pixels + y * pitch; for (unsigned int x = 0; x < width; x++) { @@ -170,23 +172,8 @@ bool CBaseTexture::LoadPaletted(unsigned int width, unsigned int height, unsigne *dest++ = col.r; *dest++ = col.x; } - // clamp to edge - repeat last column - for (unsigned int x = width; x < m_nTextureWidth; x++) - { - COLOR col = palette[*(src-1)]; - *dest++ = col.b; - *dest++ = col.g; - *dest++ = col.r; - *dest++ = col.x; - } - } - // clamp to edge - repeat last row - unsigned char *dest = m_pPixels + height*GetPitch(); - for (unsigned int y = height; y < m_nTextureHeight; y++) - { - memcpy(dest, dest-GetPitch(), GetPitch()); - dest += GetPitch(); } + ClampToEdge(); return true; } @@ -200,3 +187,53 @@ unsigned int CBaseTexture::PadPow2(unsigned int x) x |= x >> 16; return ++x; } + +unsigned int CBaseTexture::GetPitch(unsigned int width) const +{ + switch (m_format) + { + case XB_FMT_DXT1: + return ((width + 3) / 4) * 8; + case XB_FMT_DXT3: + case XB_FMT_DXT5: + case XB_FMT_DXT5_YCoCg: + return ((width + 3) / 4) * 16; + case XB_FMT_A8: + return width; + case XB_FMT_A8R8G8B8: + default: + return width*4; + } +} + +unsigned int CBaseTexture::GetRows(unsigned int height) const +{ + switch (m_format) + { + case XB_FMT_DXT1: + return (height + 3) / 4; + case XB_FMT_DXT3: + case XB_FMT_DXT5: + case XB_FMT_DXT5_YCoCg: + return (height + 3) / 4; + default: + return height; + } +} + +unsigned int CBaseTexture::GetBlockSize() const +{ + switch (m_format) + { + case XB_FMT_DXT1: + return 8; + case XB_FMT_DXT3: + case XB_FMT_DXT5: + case XB_FMT_DXT5_YCoCg: + return 16; + case XB_FMT_A8: + return 1; + default: + return 4; + } +} diff --git a/guilib/Texture.h b/guilib/Texture.h index d0f2152a0c..a4a30ce650 100644 --- a/guilib/Texture.h +++ b/guilib/Texture.h @@ -49,41 +49,44 @@ class CBaseTexture { public: - CBaseTexture(unsigned int width = 0, unsigned int height = 0, unsigned int BPP = 0, unsigned int format = XB_FMT_B8G8R8A8); + CBaseTexture(unsigned int width = 0, unsigned int height = 0, unsigned int format = XB_FMT_A8R8G8B8); virtual ~CBaseTexture(); - // TODO: Clean up this interface once things have settled down (none of these need to be virtual) - virtual bool LoadFromFile(const CStdString& texturePath); - virtual bool LoadFromMemory(unsigned int width, unsigned int height, unsigned int pitch, unsigned int BPP, unsigned int format, unsigned char* pPixels); + bool LoadFromFile(const CStdString& texturePath); + bool LoadFromMemory(unsigned int width, unsigned int height, unsigned int pitch, unsigned int format, unsigned char* pixels); bool LoadPaletted(unsigned int width, unsigned int height, unsigned int pitch, unsigned int format, const unsigned char *pixels, const COLOR *palette); virtual void CreateTextureObject() = 0; virtual void DestroyTextureObject() = 0; virtual void LoadToGPU() = 0; - XBMC::TexturePtr GetTextureObject() const { return m_pTexture; } - virtual unsigned char* GetPixels() const { return m_pPixels; } - virtual unsigned int GetPitch() const { return m_nTextureWidth * (m_nBPP / 8); } - virtual unsigned int GetTextureWidth() const { return m_nTextureWidth; }; - virtual unsigned int GetTextureHeight() const { return m_nTextureHeight; }; + XBMC::TexturePtr GetTextureObject() const { return m_texture; } + unsigned char* GetPixels() const { return m_pixels; } + unsigned int GetPitch() const { return GetPitch(m_textureWidth); } + unsigned int GetRows() const { return GetRows(m_textureHeight); } + unsigned int GetTextureWidth() const { return m_textureWidth; } + unsigned int GetTextureHeight() const { return m_textureHeight; } unsigned int GetWidth() const { return m_imageWidth; } unsigned int GetHeight() const { return m_imageHeight; } - unsigned int GetBPP() const { return m_nBPP; } - void Update(int w, int h, int pitch, unsigned int format, const unsigned char *pixels, bool loadToGPU); - void Allocate(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format); + void Update(unsigned int width, unsigned int height, unsigned int pitch, unsigned int format, const unsigned char *pixels, bool loadToGPU); + void Allocate(unsigned int width, unsigned int height, unsigned int format); + void ClampToEdge(); static unsigned int PadPow2(unsigned int x); protected: + // helpers for computation of texture parameters for compressed textures + unsigned int GetPitch(unsigned int width) const; + unsigned int GetRows(unsigned int height) const; + unsigned int GetBlockSize() const; + unsigned int m_imageWidth; unsigned int m_imageHeight; - unsigned int m_nTextureWidth; - unsigned int m_nTextureHeight; - unsigned int m_nBPP; - XBMC::TexturePtr m_pTexture; - unsigned char* m_pPixels; - unsigned int m_bufferSize; + unsigned int m_textureWidth; + unsigned int m_textureHeight; + XBMC::TexturePtr m_texture; + unsigned char* m_pixels; bool m_loadedToGPU; unsigned int m_format; }; diff --git a/guilib/TextureBundleXBT.cpp b/guilib/TextureBundleXBT.cpp index b8a1602280..beac56a831 100644 --- a/guilib/TextureBundleXBT.cpp +++ b/guilib/TextureBundleXBT.cpp @@ -40,7 +40,7 @@ #if !defined(__GNUC__) #pragma comment(lib,"../../xbmc/lib/liblzo/lzo.lib") -#pragma comment (lib,"../../xbmc/lib/libsquish/lib/squish.lib")
+#pragma comment (lib,"../../xbmc/lib/libsquish/lib/squish.lib") #endif CTextureBundleXBT::CTextureBundleXBT(void) @@ -55,8 +55,6 @@ CTextureBundleXBT::~CTextureBundleXBT(void) bool CTextureBundleXBT::OpenBundle() { - m_supportsCompressedTextures = g_Windowing.SupportsCompressedTextures(); - Cleanup(); // Find the correct texture file (skin or theme) @@ -113,8 +111,7 @@ bool CTextureBundleXBT::HasFile(const CStdString& Filename) } CStdString name = Normalize(Filename); - bool result = m_XBTFReader.Exists(name, XB_FMT_DXT5); - return result; + return m_XBTFReader.Exists(name); } void CTextureBundleXBT::GetTexturesFromPath(const CStdString &path, std::vector<CStdString> &textures) @@ -143,7 +140,7 @@ bool CTextureBundleXBT::LoadTexture(const CStdString& Filename, CBaseTexture** p { CStdString name = Normalize(Filename); - CXBTFFile* file = m_XBTFReader.Find(name, XB_FMT_DXT5); + CXBTFFile* file = m_XBTFReader.Find(name); if (!file) return false; @@ -151,7 +148,7 @@ bool CTextureBundleXBT::LoadTexture(const CStdString& Filename, CBaseTexture** p return false; CXBTFFrame& frame = file->GetFrames().at(0); - if (!ConvertFrameToTexture(Filename, frame, file->GetFormat(), ppTexture)) + if (!ConvertFrameToTexture(Filename, frame, ppTexture)) { return false; } @@ -167,7 +164,7 @@ int CTextureBundleXBT::LoadAnim(const CStdString& Filename, CBaseTexture*** ppTe { CStdString name = Normalize(Filename); - CXBTFFile* file = m_XBTFReader.Find(name, XB_FMT_DXT5); + CXBTFFile* file = m_XBTFReader.Find(name); if (!file) return false; @@ -182,7 +179,7 @@ int CTextureBundleXBT::LoadAnim(const CStdString& Filename, CBaseTexture*** ppTe { CXBTFFrame& frame = file->GetFrames().at(i); - if (!ConvertFrameToTexture(Filename, frame, file->GetFormat(), &((*ppTextures)[i]))) + if (!ConvertFrameToTexture(Filename, frame, &((*ppTextures)[i]))) { return false; } @@ -197,63 +194,75 @@ int CTextureBundleXBT::LoadAnim(const CStdString& Filename, CBaseTexture*** ppTe return nTextures; } -bool CTextureBundleXBT::ConvertFrameToTexture(const CStdString& name, CXBTFFrame& frame, int format, CBaseTexture** ppTexture) +bool CTextureBundleXBT::ConvertFrameToTexture(const CStdString& name, CXBTFFrame& frame, CBaseTexture** ppTexture) { // found texture - allocate the necessary buffers - unsigned char* PackedBuf = (unsigned char*) malloc((size_t)frame.GetPackedSize()); - if (PackedBuf == NULL) + squish::u8 *buffer = new squish::u8[(size_t)frame.GetPackedSize()]; + if (buffer == NULL) { CLog::Log(LOGERROR, "Out of memory loading texture: %s (need %llu bytes)", name.c_str(), frame.GetPackedSize()); return false; } - + // load the compressed texture - if (!m_XBTFReader.Load(frame, PackedBuf)) + if (!m_XBTFReader.Load(frame, buffer)) { CLog::Log(LOGERROR, "Error loading texture: %s", name.c_str()); - free(PackedBuf); - return false; + delete[] buffer; + return false; } - - squish::u8* UnpackedBuf = NULL; - if (!m_supportsCompressedTextures || g_Windowing.NeedPower2Texture() || format == XB_FMT_LZO) - { - UnpackedBuf = new squish::u8[frame.GetWidth() * frame.GetHeight() * 4]; - if (UnpackedBuf == NULL) + + // check if it's packed with lzo + if (frame.IsPacked()) + { // unpack + squish::u8 *unpacked = new squish::u8[(size_t)frame.GetUnpackedSize()]; + if (unpacked == NULL) { CLog::Log(LOGERROR, "Out of memory unpacking texture: %s (need %llu bytes)", name.c_str(), frame.GetUnpackedSize()); - free(PackedBuf); + delete[] buffer; return false; - } - - if (format == XB_FMT_LZO) + } + lzo_uint s = (lzo_uint)frame.GetUnpackedSize(); + if (lzo1x_decompress(buffer, (lzo_uint)frame.GetPackedSize(), unpacked, &s, NULL) != LZO_E_OK || + s != frame.GetUnpackedSize()) { - lzo_uint s = (lzo_uint)frame.GetUnpackedSize(); - if (lzo1x_decompress(PackedBuf, (lzo_uint)frame.GetPackedSize(), UnpackedBuf, &s, NULL) != LZO_E_OK || - s != frame.GetUnpackedSize()) - { - CLog::Log(LOGERROR, "Error loading texture: %s: Decompression error", name.c_str()); - free(PackedBuf); - delete [] UnpackedBuf; - return false; - } + CLog::Log(LOGERROR, "Error loading texture: %s: Decompression error", name.c_str()); + delete[] buffer; + delete[] unpacked; + return false; } - else + delete[] buffer; + buffer = unpacked; + } + unsigned int format = frame.GetFormat(); + if ((format & XB_FMT_DXT_MASK) != 0 && !g_Windowing.SupportsDXT()) + { // we don't support this texture format, so decode + squish::u8 *decoded = new squish::u8[frame.GetWidth() * frame.GetHeight() * 4]; + if (decoded == NULL) { - squish::DecompressImage(UnpackedBuf, frame.GetWidth(), frame.GetHeight(), (const squish::u8*) PackedBuf, squish::kDxt5); + CLog::Log(LOGERROR, "Out of memory unpacking texture: %s (need %llu bytes)", name.c_str(), frame.GetUnpackedSize()); + delete[] buffer; + return false; } - - format = XB_FMT_R8G8B8A8; + + if (format == XB_FMT_DXT1) + squish::DecompressImage(decoded, frame.GetWidth(), frame.GetHeight(), buffer, squish::kDxt1 | squish::kSourceBGRA); + else if (format == XB_FMT_DXT3) + squish::DecompressImage(decoded, frame.GetWidth(), frame.GetHeight(), buffer, squish::kDxt3 | squish::kSourceBGRA); + else if (format == XB_FMT_DXT5) + squish::DecompressImage(decoded, frame.GetWidth(), frame.GetHeight(), buffer, squish::kDxt5 | squish::kSourceBGRA); + + format = XB_FMT_A8R8G8B8; + delete[] buffer; + buffer = decoded; } - + // create an xbmc texture - *ppTexture = new CTexture(frame.GetWidth(), frame.GetHeight(), 32, format); - (*ppTexture)->LoadFromMemory(frame.GetWidth(), frame.GetHeight(), frame.GetWidth() * 4, 32, format, m_supportsCompressedTextures ? PackedBuf : UnpackedBuf); + *ppTexture = new CTexture(); + (*ppTexture)->LoadFromMemory(frame.GetWidth(), frame.GetHeight(), 0, format, buffer); + + delete[] buffer; - free(PackedBuf); - if (UnpackedBuf) - delete [] UnpackedBuf; - return true; } diff --git a/guilib/TextureBundleXBT.h b/guilib/TextureBundleXBT.h index a5f1d7a3b8..a9b033c2d4 100644 --- a/guilib/TextureBundleXBT.h +++ b/guilib/TextureBundleXBT.h @@ -47,12 +47,11 @@ public: private: bool OpenBundle(); - bool ConvertFrameToTexture(const CStdString& name, CXBTFFrame& frame, int format, CBaseTexture** ppTexture); + bool ConvertFrameToTexture(const CStdString& name, CXBTFFrame& frame, CBaseTexture** ppTexture); time_t m_TimeStamp; bool m_themeBundle; - bool m_supportsCompressedTextures; CXBTFReader m_XBTFReader; }; diff --git a/guilib/TextureDX.cpp b/guilib/TextureDX.cpp index 3b55ccc868..b38a4c8303 100644 --- a/guilib/TextureDX.cpp +++ b/guilib/TextureDX.cpp @@ -21,7 +21,6 @@ #include "TextureDX.h" #include "WindowingFactory.h" -#include "../xbmc/FileSystem/SpecialProtocol.h" #include "utils/log.h" #ifdef HAS_DX @@ -29,10 +28,9 @@ /************************************************************************/ /* CDXTexture */ /************************************************************************/ -CDXTexture::CDXTexture(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format) -: CBaseTexture(width, height, BPP, format) +CDXTexture::CDXTexture(unsigned int width, unsigned int height, unsigned int format) +: CBaseTexture(width, height, format) { - Allocate(m_imageWidth, m_imageHeight, m_nBPP, m_format); } CDXTexture::~CDXTexture() @@ -46,20 +44,18 @@ void CDXTexture::CreateTextureObject() switch (m_format) { - case XB_FMT_DXT1: + case XB_FMT_DXT1: format = D3DFMT_DXT1; - break; - case XB_FMT_DXT3: + break; + case XB_FMT_DXT3: format = D3DFMT_DXT3; - break; - case XB_FMT_DXT5: + break; + case XB_FMT_DXT5: + case XB_FMT_DXT5_YCoCg: format = D3DFMT_DXT5; - break; - case XB_FMT_R8G8B8A8: - format = D3DFMT_A8R8G8B8; break; - case XB_FMT_B8G8R8A8: - format = D3DFMT_A8B8G8R8; + case XB_FMT_A8R8G8B8: + format = D3DFMT_A8R8G8B8; break; case XB_FMT_A8: format = D3DFMT_A8; @@ -68,62 +64,56 @@ void CDXTexture::CreateTextureObject() return; } - SAFE_RELEASE(m_pTexture); + SAFE_RELEASE(m_texture); - D3DXCreateTexture(g_Windowing.Get3DDevice(), m_nTextureWidth, m_nTextureHeight, 1, 0, format, D3DPOOL_MANAGED , &m_pTexture); + D3DXCreateTexture(g_Windowing.Get3DDevice(), m_textureWidth, m_textureHeight, 1, 0, format, D3DPOOL_MANAGED , &m_texture); } void CDXTexture::DestroyTextureObject() { - SAFE_RELEASE(m_pTexture); + SAFE_RELEASE(m_texture); } void CDXTexture::LoadToGPU() { - if (!m_pPixels) + if (!m_pixels) { // nothing to load - probably same image (no change) return; } - if (m_pTexture == NULL) + if (m_texture == NULL) { CreateTextureObject(); - if (m_pTexture == NULL) + if (m_texture == NULL) { - CLog::Log(LOGDEBUG, "CDXTexture::CDXTexture: Error creating new texture for size %d x %d", m_nTextureWidth, m_nTextureHeight); + CLog::Log(LOGDEBUG, "CDXTexture::CDXTexture: Error creating new texture for size %d x %d", m_textureWidth, m_textureHeight); return; } } D3DLOCKED_RECT lr; - if ( D3D_OK == m_pTexture->LockRect( 0, &lr, NULL, 0 )) + if ( D3D_OK == m_texture->LockRect( 0, &lr, NULL, 0 )) { - DWORD destPitch = lr.Pitch; - - DWORD srcPitch = m_imageWidth * m_nBPP / 8; - BYTE *pixels = (BYTE *)lr.pBits; + unsigned char *dst = (unsigned char *)lr.pBits; + unsigned char *src = m_pixels; + unsigned int dstPitch = lr.Pitch; + unsigned int srcPitch = GetPitch(); - if ((m_format & XB_FMT_DXT_MASK) == 0) - { - for (unsigned int y = 0; y < m_nTextureHeight; y++) - { - BYTE *dst = pixels + y * destPitch; - BYTE *src = m_pPixels + y * srcPitch; - memcpy(dst, src, srcPitch); - } - } - else + unsigned int rows = GetRows(); + for (unsigned int y = 0; y < rows; y++) { - memcpy(pixels, m_pPixels, m_bufferSize); + memcpy(dst, src, std::min(srcPitch, dstPitch)); + src += srcPitch; + dst += dstPitch; } } - m_pTexture->UnlockRect(0); + m_texture->UnlockRect(0); - delete [] m_pPixels; - m_pPixels = NULL; + delete [] m_pixels; + m_pixels = NULL; - m_loadedToGPU = true; + m_loadedToGPU = true; } #endif diff --git a/guilib/TextureDX.h b/guilib/TextureDX.h index fc927ed582..ce15d5bcb7 100644 --- a/guilib/TextureDX.h +++ b/guilib/TextureDX.h @@ -39,7 +39,7 @@ class CDXTexture : public CBaseTexture { public: - CDXTexture(unsigned int width = 0, unsigned int height = 0, unsigned int BPP = 0, unsigned int format = XB_FMT_UNKNOWN); + CDXTexture(unsigned int width = 0, unsigned int height = 0, unsigned int format = XB_FMT_UNKNOWN); virtual ~CDXTexture(); void CreateTextureObject(); diff --git a/guilib/TextureGL.cpp b/guilib/TextureGL.cpp index 812ab626c8..a30cf671d2 100644 --- a/guilib/TextureGL.cpp +++ b/guilib/TextureGL.cpp @@ -31,14 +31,9 @@ using namespace std; /************************************************************************/ /* CGLTexture */ /************************************************************************/ -CGLTexture::CGLTexture(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format) -: CBaseTexture(width, height, BPP, format) +CGLTexture::CGLTexture(unsigned int width, unsigned int height, unsigned int format) +: CBaseTexture(width, height, format) { - m_nTextureWidth = 0; - m_nTextureHeight = 0; - - if(m_imageWidth != 0 && m_imageHeight != 0) - Allocate(m_imageWidth, m_imageHeight, m_nBPP, m_format); } CGLTexture::~CGLTexture() @@ -48,24 +43,24 @@ CGLTexture::~CGLTexture() void CGLTexture::CreateTextureObject() { - glGenTextures(1, (GLuint*) &m_pTexture); + glGenTextures(1, (GLuint*) &m_texture); } void CGLTexture::DestroyTextureObject() { - if (m_pTexture) - glDeleteTextures(1, (GLuint*) &m_pTexture); + if (m_texture) + glDeleteTextures(1, (GLuint*) &m_texture); } void CGLTexture::LoadToGPU() { - if (!m_pPixels) + if (!m_pixels) { // nothing to load - probably same image (no change) return; } - if (m_pTexture == 0) + if (m_texture == 0) { // Have OpenGL generate a texture object handle for us // this happens only one time - the first time the texture is loaded @@ -73,7 +68,7 @@ void CGLTexture::LoadToGPU() } // Bind the texture object - glBindTexture(GL_TEXTURE_2D, m_pTexture); + glBindTexture(GL_TEXTURE_2D, m_texture); // Set the texture's stretching properties glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -82,22 +77,22 @@ void CGLTexture::LoadToGPU() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); unsigned int maxSize = g_Windowing.GetMaxTextureSize(); - if (m_nTextureHeight > maxSize) + if (m_textureHeight > maxSize) { - CLog::Log(LOGERROR, "GL: Image height %d too big to fit into single texture unit, truncating to %u", m_nTextureHeight, maxSize); - m_nTextureHeight = maxSize; + CLog::Log(LOGERROR, "GL: Image height %d too big to fit into single texture unit, truncating to %u", m_textureHeight, maxSize); + m_textureHeight = maxSize; } - if (m_nTextureWidth > maxSize) + if (m_textureWidth > maxSize) { - CLog::Log(LOGERROR, "GL: Image width %d too big to fit into single texture unit, truncating to %u", m_nTextureWidth, maxSize); + CLog::Log(LOGERROR, "GL: Image width %d too big to fit into single texture unit, truncating to %u", m_textureWidth, maxSize); #ifndef HAS_GLES - glPixelStorei(GL_UNPACK_ROW_LENGTH, m_nTextureWidth); + glPixelStorei(GL_UNPACK_ROW_LENGTH, m_textureWidth); #endif - m_nTextureWidth = maxSize; + m_textureWidth = maxSize; } GLenum format; - + switch (m_format) { case XB_FMT_DXT1: @@ -107,11 +102,10 @@ void CGLTexture::LoadToGPU() format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; case XB_FMT_DXT5: + case XB_FMT_DXT5_YCoCg: format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; - case XB_FMT_R8G8B8A8: - format = GL_RGBA; - break; + case XB_FMT_A8R8G8B8: default: #ifdef HAS_GL format = GL_BGRA; @@ -120,26 +114,26 @@ void CGLTexture::LoadToGPU() #endif break; } - + if ((m_format & XB_FMT_DXT_MASK) == 0) { - glTexImage2D(GL_TEXTURE_2D, 0, 4, m_nTextureWidth, m_nTextureHeight, 0, - format, GL_UNSIGNED_BYTE, m_pPixels); + glTexImage2D(GL_TEXTURE_2D, 0, 4, m_textureWidth, m_textureHeight, 0, + format, GL_UNSIGNED_BYTE, m_pixels); } else { glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, - m_nTextureWidth, m_nTextureHeight, 0, m_bufferSize, m_pPixels); + m_textureWidth, m_textureHeight, 0, GetPitch() * GetRows(), m_pixels); } - + #ifndef HAS_GLES glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); #endif VerifyGLState(); - delete [] m_pPixels; - m_pPixels = NULL; + delete [] m_pixels; + m_pixels = NULL; - m_loadedToGPU = true; + m_loadedToGPU = true; } #endif // HAS_GL diff --git a/guilib/TextureGL.h b/guilib/TextureGL.h index 8631beae2a..4197601563 100644 --- a/guilib/TextureGL.h +++ b/guilib/TextureGL.h @@ -39,9 +39,9 @@ class CGLTexture : public CBaseTexture { public: - CGLTexture(unsigned int width = 0, unsigned int height = 0, unsigned int BPP = 0, unsigned int format = XB_FMT_B8G8R8A8); + CGLTexture(unsigned int width = 0, unsigned int height = 0, unsigned int format = XB_FMT_A8R8G8B8); virtual ~CGLTexture(); - + void CreateTextureObject(); virtual void DestroyTextureObject(); void LoadToGPU(); diff --git a/guilib/TextureManager.cpp b/guilib/TextureManager.cpp index c734d33a6a..42f459d516 100644 --- a/guilib/TextureManager.cpp +++ b/guilib/TextureManager.cpp @@ -362,7 +362,7 @@ int CGUITextureManager::Load(const CStdString& strTextureName, bool checkBundleO if (glTexture) { CAnimatedGif* pImage = AnimatedGifSet.m_vecimg[iImage]; - glTexture->LoadPaletted(pImage->Width, pImage->Height, pImage->BytesPerRow, XB_FMT_B8G8R8A8, (unsigned char *)pImage->Raster, palette); + glTexture->LoadPaletted(pImage->Width, pImage->Height, pImage->BytesPerRow, XB_FMT_A8R8G8B8, (unsigned char *)pImage->Raster, palette); pMap->Add(glTexture, pImage->Delay); } } // of for (int iImage=0; iImage < iImages; iImage++) diff --git a/guilib/XBTF.cpp b/guilib/XBTF.cpp index ce6e79112e..839cfe4e0e 100644 --- a/guilib/XBTF.cpp +++ b/guilib/XBTF.cpp @@ -28,6 +28,7 @@ CXBTFFrame::CXBTFFrame() m_packedSize = 0; m_unpackedSize = 0; m_offset = 0; + m_format = XB_FMT_UNKNOWN; } uint32_t CXBTFFrame::GetWidth() const @@ -60,6 +61,11 @@ void CXBTFFrame::SetPackedSize(uint64_t size) m_packedSize = size; } +bool CXBTFFrame::IsPacked() const +{ + return m_unpackedSize != m_packedSize; +} + uint64_t CXBTFFrame::GetUnpackedSize() const { return m_unpackedSize; @@ -70,24 +76,14 @@ void CXBTFFrame::SetUnpackedSize(uint64_t size) m_unpackedSize = size; } -void CXBTFFrame::SetX(uint32_t x) -{ - m_x = x; -} - -uint32_t CXBTFFrame::GetX() const -{ - return m_x; -} - -void CXBTFFrame::SetY(uint32_t y) +void CXBTFFrame::SetFormat(uint32_t format) { - m_y = y; + m_format = format; } -uint32_t CXBTFFrame::GetY() const +uint32_t CXBTFFrame::GetFormat() const { - return m_y; + return m_format; } uint64_t CXBTFFrame::GetOffset() const @@ -110,19 +106,17 @@ void CXBTFFrame::SetDuration(uint32_t duration) m_duration = duration; } - uint64_t CXBTFFrame::GetHeaderSize() const { - uint64_t result = + uint64_t result = sizeof(m_width) + sizeof(m_height) + - sizeof(m_x) + - sizeof(m_y) + + sizeof(m_format) + sizeof(m_packedSize) + sizeof(m_unpackedSize) + - sizeof(m_offset) + - sizeof(m_duration); - + sizeof(m_offset) + + sizeof(m_duration); + return result; } @@ -130,14 +124,12 @@ CXBTFFile::CXBTFFile() { memset(m_path, 0, sizeof(m_path)); m_loop = 0; - m_format = XB_FMT_UNKNOWN; } CXBTFFile::CXBTFFile(const CXBTFFile& ref) { strcpy(m_path, ref.m_path); m_loop = ref.m_loop; - m_format = ref.m_format; m_frames = ref.m_frames; } @@ -162,16 +154,6 @@ void CXBTFFile::SetLoop(uint32_t loop) m_loop = loop; } -uint32_t CXBTFFile::GetFormat() const -{ - return m_format; -} - -void CXBTFFile::SetFormat(uint32_t format) -{ - m_format = format; -} - std::vector<CXBTFFrame>& CXBTFFile::GetFrames() { return m_frames; @@ -182,14 +164,13 @@ uint64_t CXBTFFile::GetHeaderSize() const uint64_t result = sizeof(m_path) + sizeof(m_loop) + - sizeof(m_format) + sizeof(uint32_t); /* Number of frames */ - + for (size_t i = 0; i < m_frames.size(); i++) { result += m_frames[i].GetHeaderSize(); } - + return result; } @@ -199,20 +180,20 @@ CXBTF::CXBTF() uint64_t CXBTF::GetHeaderSize() const { - uint64_t result = - 4 /* Magic */ + + uint64_t result = + 4 /* Magic */ + 1 /* Vesion */ + sizeof(uint32_t) /* Number of Files */; - + for (size_t i = 0; i < m_files.size(); i++) { result += m_files[i].GetHeaderSize(); } - + return result; } std::vector<CXBTFFile>& CXBTF::GetFiles() { - return m_files; + return m_files; } diff --git a/guilib/XBTF.h b/guilib/XBTF.h index aa26a2af59..83ffa06193 100644 --- a/guilib/XBTF.h +++ b/guilib/XBTF.h @@ -26,28 +26,25 @@ #include <stdint.h> #define XBTF_MAGIC "XBTF" -#define XBTF_VERSION "1" +#define XBTF_VERSION "2" -#define XB_FMT_DXT_MASK 14 -#define XB_FMT_UNKNOWN 1 -#define XB_FMT_DXT1 2 -#define XB_FMT_DXT3 4 -#define XB_FMT_DXT5 8 -#define XB_FMT_B8G8R8A8 16 -#define XB_FMT_R8G8B8A8 32 -#define XB_FMT_LZO 64 -#define XB_FMT_A8 128 +#define XB_FMT_DXT_MASK 15 +#define XB_FMT_UNKNOWN 0 +#define XB_FMT_DXT1 1 +#define XB_FMT_DXT3 2 +#define XB_FMT_DXT5 4 +#define XB_FMT_DXT5_YCoCg 8 +#define XB_FMT_A8R8G8B8 16 +#define XB_FMT_A8 32 class CXBTFFrame { -public: +public: CXBTFFrame(); uint32_t GetWidth() const; void SetWidth(uint32_t width); - uint32_t GetX() const; - void SetX(uint32_t x); - uint32_t GetY() const; - void SetY(uint32_t y); + uint32_t GetFormat() const; + void SetFormat(uint32_t format); uint32_t GetHeight() const; void SetHeight(uint32_t height); uint64_t GetUnpackedSize() const; @@ -59,12 +56,12 @@ public: uint64_t GetHeaderSize() const; uint32_t GetDuration() const; void SetDuration(uint32_t duration); + bool IsPacked() const; private: uint32_t m_width; uint32_t m_height; - uint32_t m_x; - uint32_t m_y; + uint32_t m_format; uint64_t m_packedSize; uint64_t m_unpackedSize; uint64_t m_offset; @@ -80,16 +77,12 @@ public: void SetPath(const std::string& path); uint32_t GetLoop() const; void SetLoop(uint32_t loop); - uint32_t GetFormat() const; - void SetFormat(uint32_t format); - - std::vector<CXBTFFrame>& GetFrames(); + std::vector<CXBTFFrame>& GetFrames(); uint64_t GetHeaderSize() const; - + private: char m_path[256]; uint32_t m_loop; - uint32_t m_format; std::vector<CXBTFFrame> m_frames; }; @@ -98,8 +91,8 @@ class CXBTF public: CXBTF(); uint64_t GetHeaderSize() const; - std::vector<CXBTFFile>& GetFiles(); - + std::vector<CXBTFFile>& GetFiles(); + private: std::vector<CXBTFFile> m_files; }; diff --git a/guilib/XBTFReader.cpp b/guilib/XBTFReader.cpp index 65bc959958..774cc8269f 100644 --- a/guilib/XBTFReader.cpp +++ b/guilib/XBTFReader.cpp @@ -84,8 +84,6 @@ bool CXBTFReader::Open(const CStdString& fileName) READ_STR(file.GetPath(), 256, m_file); READ_U32(u32, m_file); - file.SetFormat(u32); - READ_U32(u32, m_file); file.SetLoop(u32); unsigned int nofFrames; @@ -100,9 +98,7 @@ bool CXBTFReader::Open(const CStdString& fileName) READ_U32(u32, m_file); frame.SetHeight(u32); READ_U32(u32, m_file); - frame.SetX(u32); - READ_U32(u32, m_file); - frame.SetY(u32); + frame.SetFormat(u32); READ_U64(u64, m_file); frame.SetPackedSize(u64); READ_U64(u64, m_file); @@ -117,8 +113,7 @@ bool CXBTFReader::Open(const CStdString& fileName) m_xbtf.GetFiles().push_back(file); - std::pair<CStdString, unsigned int> key = std::make_pair(file.GetPath(), file.GetFormat()); - m_filesMap[key] = file; + m_filesMap[file.GetPath()] = file; } // Sanity check @@ -160,16 +155,14 @@ time_t CXBTFReader::GetLastModificationTimestamp() return fileStat.st_mtime; } -bool CXBTFReader::Exists(const CStdString& name, int formatMask) +bool CXBTFReader::Exists(const CStdString& name) { - return Find(name, formatMask) != NULL; + return Find(name) != NULL; } -CXBTFFile* CXBTFReader::Find(const CStdString& name, int formatMask) +CXBTFFile* CXBTFReader::Find(const CStdString& name) { - std::pair<CStdString, unsigned int> key = std::make_pair(name, formatMask); - - std::map<std::pair<CStdString, unsigned int>, CXBTFFile>::iterator iter = m_filesMap.find(key); + std::map<CStdString, CXBTFFile>::iterator iter = m_filesMap.find(name); if (iter == m_filesMap.end()) { return NULL; diff --git a/guilib/XBTFReader.h b/guilib/XBTFReader.h index a24d44084d..27264d3333 100644 --- a/guilib/XBTFReader.h +++ b/guilib/XBTFReader.h @@ -35,8 +35,8 @@ public: bool Open(const CStdString& fileName); void Close(); time_t GetLastModificationTimestamp(); - bool Exists(const CStdString& name, int formatMask); - CXBTFFile* Find(const CStdString& name, int formatMask); + bool Exists(const CStdString& name); + CXBTFFile* Find(const CStdString& name); bool Load(const CXBTFFrame& frame, unsigned char* buffer); std::vector<CXBTFFile>& GetFiles(); @@ -44,7 +44,7 @@ private: CXBTF m_xbtf; CStdString m_fileName; FILE* m_file; - std::map<std::pair<CStdString, unsigned int>, CXBTFFile> m_filesMap; + std::map<CStdString, CXBTFFile> m_filesMap; }; #endif diff --git a/tools/XBMCTexXBT/Win32/TexturePacker.vcproj b/tools/XBMCTexXBT/Win32/TexturePacker.vcproj index 86c48f7c17..0519601699 100644 --- a/tools/XBMCTexXBT/Win32/TexturePacker.vcproj +++ b/tools/XBMCTexXBT/Win32/TexturePacker.vcproj @@ -61,7 +61,7 @@ />
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="SDL.lib SDL_image.lib ..\..\..\xbmc\lib\libsquish\lib\squish.lib"
+ AdditionalDependencies="SDL.lib SDL_image.lib ..\..\..\xbmc\lib\libsquish\lib\squishd.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
diff --git a/tools/XBMCTexXBT/XBMCTex.cpp b/tools/XBMCTexXBT/XBMCTex.cpp index 2692f99eab..4374fd3cc9 100644 --- a/tools/XBMCTexXBT/XBMCTex.cpp +++ b/tools/XBMCTexXBT/XBMCTex.cpp @@ -36,22 +36,47 @@ #define DIR_SEPARATOR "/" #define DIR_SEPARATOR_CHAR '/' +#define FLAGS_USE_LZO 1 +#define FLAGS_ALLOW_YCOCG 2 + #undef main +const char *GetFormatString(unsigned int format) +{ + switch (format) + { + case XB_FMT_DXT1: + return "DXT1 "; + case XB_FMT_DXT3: + return "DXT3 "; + case XB_FMT_DXT5: + return "DXT5 "; + case XB_FMT_DXT5_YCoCg: + return "YCoCg"; + case XB_FMT_A8R8G8B8: + return "ARGB "; + case XB_FMT_A8: + return "A8 "; + default: + return "?????"; + } +} + // returns true for png, bmp, tga, jpg and dds files, otherwise returns false bool IsGraphicsFile(char *strFileName) { size_t n = strlen(strFileName); if (n < 4) return false; - + if (strncasecmp(&strFileName[n-4], ".png", 4) && - strncasecmp(&strFileName[n-4], ".bmp", 4) && - strncasecmp(&strFileName[n-4], ".tga", 4) && - strncasecmp(&strFileName[n-4], ".gif", 4) && - strncasecmp(&strFileName[n-4], ".jpg", 4)) + strncasecmp(&strFileName[n-4], ".bmp", 4) && + strncasecmp(&strFileName[n-4], ".tga", 4) && + strncasecmp(&strFileName[n-4], ".gif", 4) && + strncasecmp(&strFileName[n-4], ".tbn", 4) && + strncasecmp(&strFileName[n-4], ".jpg", 4)) return false; - + return true; } @@ -61,10 +86,10 @@ bool IsGIF(const char *strFileName) size_t n = strlen(strFileName); if (n < 4) return false; - + if (strncasecmp(&strFileName[n-4], ".gif", 4)) return false; - + return true; } @@ -72,14 +97,14 @@ void CreateSkeletonHeaderImpl(CXBTF& xbtf, std::string fullPath, std::string rel { struct dirent* dp; DIR *dirp = opendir(fullPath.c_str()); - + while ((dp = readdir(dirp)) != NULL) { if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { continue; } - + if (dp->d_type == DT_DIR) { std::string tmpPath = relativePath; @@ -87,9 +112,8 @@ void CreateSkeletonHeaderImpl(CXBTF& xbtf, std::string fullPath, std::string rel { tmpPath += "/"; } - - CreateSkeletonHeaderImpl(xbtf, fullPath + DIR_SEPARATOR + dp->d_name, - tmpPath + dp->d_name); + + CreateSkeletonHeaderImpl(xbtf, fullPath + DIR_SEPARATOR + dp->d_name, tmpPath + dp->d_name); } else if (IsGraphicsFile(dp->d_name)) { @@ -99,81 +123,137 @@ void CreateSkeletonHeaderImpl(CXBTF& xbtf, std::string fullPath, std::string rel fileName += relativePath; fileName += "/"; } - + fileName += dp->d_name; CXBTFFile file; file.SetPath(fileName); - file.SetFormat(XB_FMT_DXT5); xbtf.GetFiles().push_back(file); } } - + closedir(dirp); } void CreateSkeletonHeader(CXBTF& xbtf, std::string fullPath) { std::string temp; - CreateSkeletonHeaderImpl(xbtf, fullPath, temp); + CreateSkeletonHeaderImpl(xbtf, fullPath, temp); +} + +CXBTFFrame appendContent(CXBTFWriter &writer, int width, int height, unsigned char const *data, unsigned int size, unsigned int format, unsigned int flags) +{ + CXBTFFrame frame; + unsigned int compressedSize = size; + if ((flags & FLAGS_USE_LZO) == FLAGS_USE_LZO) + { // TODO: add lzo'ing + } + else + { + writer.AppendContent(data, size); + } + frame.SetPackedSize(compressedSize); + frame.SetUnpackedSize(size); + frame.SetWidth(width); + frame.SetHeight(height); + frame.SetFormat(format); + frame.SetDuration(0); + return frame; +} + +void CompressImage(const squish::u8 *brga, int width, int height, squish::u8 *compressed, unsigned int flags, double &colorMSE, double &alphaMSE) +{ + squish::CompressImage(brga, width, height, compressed, flags | squish::kSourceBGRA); + squish::ComputeMSE(brga, width, height, compressed, flags | squish::kSourceBGRA, colorMSE, alphaMSE); } -CXBTFFrame createXBTFFrame(SDL_Surface* image, CXBTFWriter& writer, unsigned int format) +CXBTFFrame createXBTFFrame(SDL_Surface* image, CXBTFWriter& writer, double maxMSE, unsigned int flags) { - // Convert to RGBA - SDL_PixelFormat rgbaFormat; - memset(&rgbaFormat, 0, sizeof(SDL_PixelFormat)); - rgbaFormat.BitsPerPixel = 32; - rgbaFormat.BytesPerPixel = 4; - + // Convert to ARGB + SDL_PixelFormat argbFormat; + memset(&argbFormat, 0, sizeof(SDL_PixelFormat)); + argbFormat.BitsPerPixel = 32; + argbFormat.BytesPerPixel = 4; + // For DXT5 we need RGBA -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - rgbaFormat.Rmask = 0x000000ff; - rgbaFormat.Rshift = 0; - rgbaFormat.Gmask = 0x0000ff00; - rgbaFormat.Gshift = 8; - rgbaFormat.Bmask = 0x00ff0000; - rgbaFormat.Bshift = 16; - rgbaFormat.Amask = 0xff000000; - rgbaFormat.Ashift = 24; -#else - rgbaFormat.Amask = 0x000000ff; - rgbaFormat.Ashift = 0; - rgbaFormat.Rmask = 0x0000ff00; - rgbaFormat.Rshift = 8; - rgbaFormat.Gmask = 0x00ff0000; - rgbaFormat.Gshift = 16; - rgbaFormat.Bmask = 0xff000000; - rgbaFormat.Bshift = 24; +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + argbFormat.Amask = 0xff000000; + argbFormat.Ashift = 24; + argbFormat.Rmask = 0x00ff0000; + argbFormat.Rshift = 16; + argbFormat.Gmask = 0x0000ff00; + argbFormat.Gshift = 8; + argbFormat.Bmask = 0x000000ff; + argbFormat.Bshift = 0; +#else + argbFormat.Amask = 0x000000ff; + argbFormat.Ashift = 0; + argbFormat.Rmask = 0x0000ff00; + argbFormat.Rshift = 8; + argbFormat.Gmask = 0x00ff0000; + argbFormat.Gshift = 16; + argbFormat.Bmask = 0xff000000; + argbFormat.Bshift = 24; #endif - - SDL_Surface *rgbaImage = SDL_ConvertSurface(image, &rgbaFormat, 0); + SDL_Surface *argbImage = SDL_ConvertSurface(image, &argbFormat, 0); - int compressedSize = 0; - CXBTFFrame frame; - - // Compress to DXT5 - compressedSize = squish::GetStorageRequirements(image->w, rgbaImage->h, squish::kDxt5); - squish::u8* compressed = new squish::u8[compressedSize]; - squish::CompressImage((const squish::u8*) rgbaImage->pixels, image->w, rgbaImage->h, compressed, squish::kDxt5); - frame.SetPackedSize(compressedSize); - frame.SetUnpackedSize(compressedSize); - - // Write the texture to a temporary file - writer.AppendContent((unsigned char*) compressed, compressedSize); - - delete [] compressed; - - SDL_FreeSurface(rgbaImage); - - // Update the header - frame.SetWidth(image->w); - frame.SetHeight(image->h); - frame.SetX(0); - frame.SetY(0); - frame.SetDuration(0); - + unsigned int format = 0; + double colorMSE, alphaMSE; + squish::u8* argb = (squish::u8 *)argbImage->pixels; + unsigned int compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt5); + squish::u8* compressed = new squish::u8[compressedSize]; + // first try DXT1, which is only 4bits/pixel + CompressImage(argb, image->w, image->h, compressed, squish::kDxt1, colorMSE, alphaMSE); + if (colorMSE < maxMSE && alphaMSE < maxMSE) + { // success - use it + compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt1); + format = XB_FMT_DXT1; + } + if (!format && alphaMSE == 0 && (flags & FLAGS_ALLOW_YCOCG) == FLAGS_ALLOW_YCOCG) + { // no alpha channel, so DXT5YCoCg is going to be the best DXT5 format +/* CompressImage(argb, image->w, image->h, compressed, squish::kDxt5 | squish::kUseYCoCg, colorMSE, alphaMSE); + if (colorMSE < maxMSE && alphaMSE < maxMSE) + { // success - use it + compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt5); + format = XB_FMT_DXT5_YCoCg; + } + */ + } + if (!format) + { // try DXT3 and DXT5 - use whichever is better (color is the same, but alpha will be different) + CompressImage(argb, image->w, image->h, compressed, squish::kDxt3, colorMSE, alphaMSE); + if (colorMSE < maxMSE) + { // color is fine, test DXT5 as well + double dxt5MSE; + squish::u8* compressed2 = new squish::u8[squish::GetStorageRequirements(image->w, image->h, squish::kDxt5)]; + CompressImage(argb, image->w, image->h, compressed2, squish::kDxt5, colorMSE, dxt5MSE); + if (alphaMSE < maxMSE && alphaMSE < dxt5MSE) + { // DXT3 passes and is best + compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt3); + format = XB_FMT_DXT3; + } + else if (dxt5MSE < maxMSE) + { // DXT5 passes + compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt5); + memcpy(compressed, compressed2, compressedSize); + format = XB_FMT_DXT5; + } + delete[] compressed2; + } + } + CXBTFFrame frame; + if (!format) + { // none of the compressed stuff works for us, so we use 32bit texture + format = XB_FMT_A8R8G8B8; + frame = appendContent(writer, image->w, image->h, argb, image->w * image->h * 4, format, flags); + } + else + { + frame = appendContent(writer, image->w, image->h, compressed, compressedSize, format, flags); + } + delete[] compressed; + SDL_FreeSurface(argbImage); return frame; } @@ -185,73 +265,75 @@ void Usage() puts(" -output <dir> Output directory/filename. Default: Textures.xpr"); } -int createBundle(const std::string& InputDir, const std::string& OutputFile) +int createBundle(const std::string& InputDir, const std::string& OutputFile, double maxMSE, unsigned int flags) { CXBTF xbtf; CreateSkeletonHeader(xbtf, InputDir); - + CXBTFWriter writer(xbtf, OutputFile); if (!writer.Create()) { printf("Error creating file\n"); return 1; } - + std::vector<CXBTFFile>& files = xbtf.GetFiles(); for (size_t i = 0; i < files.size(); i++) { CXBTFFile& file = files[i]; - - int format = file.GetFormat(); - - printf("Converting %s to DXT5 ", file.GetPath()); - + std::string fullPath = InputDir; fullPath += file.GetPath(); - + + std::string output = file.GetPath(); + output = output.substr(0, 40); + while (output.size() < 46) + output += ' '; if (!IsGIF(fullPath.c_str())) - { + { // Load the image SDL_Surface* image = IMG_Load(fullPath.c_str()); if (!image) { - printf("...unable to load image\n"); + printf("...unable to load image %s\n", file.GetPath()); continue; } - - CXBTFFrame frame = createXBTFFrame(image, writer, format); - - file.SetLoop(0); - file.GetFrames().push_back(frame); - - printf("(%dx%d)\n", image->w, image->h); - - SDL_FreeSurface(image); + + printf(output.c_str()); + + CXBTFFrame frame = createXBTFFrame(image, writer, maxMSE, flags); + + printf("%s (%d,%d @ %d bytes)\n", GetFormatString(frame.GetFormat()), frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize()); + + file.SetLoop(0); + file.GetFrames().push_back(frame); + + SDL_FreeSurface(image); } else { - int gnAG = AG_LoadGIF(fullPath.c_str(), NULL, 0); + int gnAG = AG_LoadGIF(fullPath.c_str(), NULL, 0); AG_Frame* gpAG = new AG_Frame[gnAG]; AG_LoadGIF(fullPath.c_str(), gpAG, gnAG); - - printf("(%dx%d) -- %d frames\n", gpAG[0].surface->w, gpAG[0].surface->h, gnAG); - + + printf("%s\n", output.c_str()); + for (int j = 0; j < gnAG; j++) { - CXBTFFrame frame = createXBTFFrame(gpAG[j].surface, writer, format); - frame.SetX(gpAG[j].x); - frame.SetX(gpAG[j].y); + printf(" frame %4i ", j); + CXBTFFrame frame = createXBTFFrame(gpAG[j].surface, writer, maxMSE, flags); frame.SetDuration(gpAG[j].delay); - file.GetFrames().push_back(frame); + file.GetFrames().push_back(frame); + printf("%s (%d,%d @ %d bytes)\n", GetFormatString(frame.GetFormat()), frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize()); } AG_FreeSurfaces(gpAG, gnAG); delete [] gpAG; - - file.SetLoop(0); - } + + file.SetLoop(0); + } } - + if (!writer.UpdateHeader()) { printf("Error writing header to file\n"); @@ -263,13 +345,13 @@ int createBundle(const std::string& InputDir, const std::string& OutputFile) printf("Error closing file\n"); return 1; } - + return 0; } int main(int argc, char* argv[]) { - bool valid = false; + bool valid = false; CmdLineArgs args(argc, (const char**)argv); if (args.size() == 1) @@ -312,13 +394,13 @@ int main(int argc, char* argv[]) { Usage(); return 1; - } - + } + size_t pos = InputDir.find_last_of(DIR_SEPARATOR); - if (pos != InputDir.length()-1) - { + if (pos != InputDir.length() - 1) InputDir += DIR_SEPARATOR; - } - - createBundle(InputDir, OutputFilename); + + double maxMSE = 1.5; // HQ only please + unsigned int flags = 0; // TODO: currently no YCoCg and no LZO (commandline option?) + createBundle(InputDir, OutputFilename, maxMSE, flags); } diff --git a/tools/XBMCTexXBT/XBTFWriter.cpp b/tools/XBMCTexXBT/XBTFWriter.cpp index b5b94e800c..eea8195382 100644 --- a/tools/XBMCTexXBT/XBTFWriter.cpp +++ b/tools/XBMCTexXBT/XBTFWriter.cpp @@ -23,13 +23,13 @@ bool CXBTFWriter::Create() { return false; } - + m_tempFile = fopen(TEMP_FILE, "wb"); if (m_tempFile == NULL) { return false; } - + return true; } @@ -46,30 +46,30 @@ bool CXBTFWriter::Close() { return false; } - + unsigned char* tmp = new unsigned char[10*1024*1024]; size_t bytesRead; while ((bytesRead = fread(tmp, 1, TEMP_SIZE, m_tempFile)) > 0) { fwrite(tmp, bytesRead, 1, m_file); } - + fclose(m_file); fclose(m_tempFile); unlink(TEMP_FILE); - + return true; } -bool CXBTFWriter::AppendContent(unsigned char* data, size_t length) +bool CXBTFWriter::AppendContent(unsigned char const* data, size_t length) { if (m_tempFile == NULL) { return false; } - + fwrite(data, length, 1, m_tempFile); - + return true; } @@ -79,18 +79,18 @@ bool CXBTFWriter::UpdateHeader() { return false; } - + uint64_t offset = m_xbtf.GetHeaderSize(); - + WRITE_STR(XBTF_MAGIC, 4, m_file); WRITE_STR(XBTF_VERSION, 1, m_file); - + std::vector<CXBTFFile>& files = m_xbtf.GetFiles(); WRITE_U32(files.size(), m_file); for (size_t i = 0; i < files.size(); i++) { CXBTFFile& file = files[i]; - + // Convert path to lower case char* ch = file.GetPath(); while (*ch) @@ -98,11 +98,10 @@ bool CXBTFWriter::UpdateHeader() *ch = tolower(*ch); ch++; } - + WRITE_STR(file.GetPath(), 256, m_file); - WRITE_U32(file.GetFormat(), m_file); WRITE_U32(file.GetLoop(), m_file); - + std::vector<CXBTFFrame>& frames = file.GetFrames(); WRITE_U32(frames.size(), m_file); for (size_t j = 0; j < frames.size(); j++) @@ -110,18 +109,17 @@ bool CXBTFWriter::UpdateHeader() CXBTFFrame& frame = frames[j]; frame.SetOffset(offset); offset += frame.GetPackedSize(); - + WRITE_U32(frame.GetWidth(), m_file); WRITE_U32(frame.GetHeight(), m_file); - WRITE_U32(frame.GetX(), m_file); - WRITE_U32(frame.GetY(), m_file); + WRITE_U32(frame.GetFormat(), m_file); WRITE_U64(frame.GetPackedSize(), m_file); WRITE_U64(frame.GetUnpackedSize(), m_file); WRITE_U32(frame.GetDuration(), m_file); WRITE_U64(frame.GetOffset(), m_file); } } - + // Sanity check int64_t pos = ftell(m_file); if (pos != m_xbtf.GetHeaderSize()) @@ -129,6 +127,6 @@ bool CXBTFWriter::UpdateHeader() printf("Expected header size (%" PRId64 ") != actual size (%" PRId64 ")\n", m_xbtf.GetHeaderSize(), pos); return false; } - + return true; } diff --git a/tools/XBMCTexXBT/XBTFWriter.h b/tools/XBMCTexXBT/XBTFWriter.h index 810f3ddce3..806c468ee6 100644 --- a/tools/XBMCTexXBT/XBTFWriter.h +++ b/tools/XBMCTexXBT/XBTFWriter.h @@ -11,9 +11,9 @@ public: CXBTFWriter(CXBTF& xbtf, const std::string outputFile); bool Create(); bool Close(); - bool AppendContent(unsigned char* data, size_t length); + bool AppendContent(unsigned char const* data, size_t length); bool UpdateHeader(); - + private: CXBTF& m_xbtf; std::string m_outputFile; diff --git a/xbmc/GUIDialogTeletext.cpp b/xbmc/GUIDialogTeletext.cpp index 71eaac0273..682a8e4497 100644 --- a/xbmc/GUIDialogTeletext.cpp +++ b/xbmc/GUIDialogTeletext.cpp @@ -99,7 +99,7 @@ void CGUIDialogTeletext::Render() unsigned char* textureBuffer = (unsigned char*)m_TextDecoder.GetTextureBuffer(); if (!m_bClose && m_TextDecoder.NeedRendering() && textureBuffer) { - m_pTxtTexture->Update(m_TextDecoder.GetWidth(), m_TextDecoder.GetHeight(), m_TextDecoder.GetWidth()*4, XB_FMT_B8G8R8A8, textureBuffer, false); + m_pTxtTexture->Update(m_TextDecoder.GetWidth(), m_TextDecoder.GetHeight(), m_TextDecoder.GetWidth()*4, XB_FMT_A8R8G8B8, textureBuffer, false); m_TextDecoder.RenderingDone(); } @@ -127,7 +127,7 @@ void CGUIDialogTeletext::OnInitWindow() Close(); } - m_pTxtTexture = new CTexture(m_TextDecoder.GetWidth(), m_TextDecoder.GetHeight(), 32, XB_FMT_B8G8R8A8); + m_pTxtTexture = new CTexture(m_TextDecoder.GetWidth(), m_TextDecoder.GetHeight(), XB_FMT_A8R8G8B8); if (!m_pTxtTexture) { CLog::Log(LOGERROR, "%s: failed to create texture", __FUNCTION__); diff --git a/xbmc/Picture.cpp b/xbmc/Picture.cpp index 55b3c0cfa0..2fb86aa6be 100644 --- a/xbmc/Picture.cpp +++ b/xbmc/Picture.cpp @@ -55,7 +55,7 @@ bool CPicture::Load(const CStdString& strFileName, CBaseTexture* pTexture, int i return false; } - pTexture->Allocate(m_info.width, m_info.height, 32, XB_FMT_B8G8R8A8); + pTexture->Allocate(m_info.width, m_info.height, XB_FMT_A8R8G8B8); if (pTexture) { diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp index 11791502f9..ae2e7f2685 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.cpp +++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp @@ -1299,7 +1299,7 @@ void CWinRenderer::CreateThumbnail(CBaseTexture *texture, unsigned int width, un D3DLOCKED_RECT lockedRect; if (D3D_OK == surface->LockRect(&lockedRect, NULL, NULL)) { - texture->LoadFromMemory(width, height, lockedRect.Pitch, XB_FMT_B8G8R8A8, 32, (unsigned char *)lockedRect.pBits); + texture->LoadFromMemory(width, height, lockedRect.Pitch, XB_FMT_A8R8G8B8, (unsigned char *)lockedRect.pBits); surface->UnlockRect(); } surface->Release(); diff --git a/xbmc/karaoke/karaokelyricscdg.cpp b/xbmc/karaoke/karaokelyricscdg.cpp index 27080e3ad7..a716058c56 100644 --- a/xbmc/karaoke/karaokelyricscdg.cpp +++ b/xbmc/karaoke/karaokelyricscdg.cpp @@ -151,7 +151,7 @@ void CKaraokeLyricsCDG::Render() if (buf) { RenderIntoBuffer( buf, WIDTH, HEIGHT, WIDTH * 4 ); - m_pCdgTexture->Update( WIDTH, HEIGHT, WIDTH * 4, XB_FMT_B8G8R8A8, buf, false ); + m_pCdgTexture->Update( WIDTH, HEIGHT, WIDTH * 4, XB_FMT_A8R8G8B8, buf, false ); } delete [] buf; |