aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryuvalt <yuvalt@svn>2009-09-28 11:22:33 +0000
committeryuvalt <yuvalt@svn>2009-09-28 11:22:33 +0000
commit06626487ad04850a6bb66ed55aced8c62f855f4e (patch)
tree0c4e4856ce98b26b37f09afba0f1f3481dbc94cd
parent7ce41e8e293e15aa067dd691517ddb3fab2b3adf (diff)
support DXT5 textures with a new texture bundle(r)
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@23209 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
-rw-r--r--Makefile.in14
-rw-r--r--guilib/DirectXGraphics.cpp7
-rw-r--r--guilib/Makefile6
-rw-r--r--guilib/Texture.cpp83
-rw-r--r--guilib/Texture.h13
-rw-r--r--guilib/TextureBundle.cpp499
-rw-r--r--guilib/TextureBundle.h38
-rw-r--r--guilib/TextureBundleXBT.cpp281
-rw-r--r--guilib/TextureBundleXBT.h59
-rw-r--r--guilib/TextureBundleXPR.cpp487
-rw-r--r--guilib/TextureBundleXPR.h69
-rw-r--r--guilib/TextureDX.cpp6
-rw-r--r--guilib/TextureDX.h2
-rw-r--r--guilib/TextureGL.cpp43
-rw-r--r--guilib/TextureGL.h2
-rw-r--r--guilib/TextureManager.cpp5
-rw-r--r--guilib/XBTF.cpp218
-rw-r--r--guilib/XBTF.h105
-rw-r--r--guilib/XBTFReader.cpp201
-rw-r--r--guilib/XBTFReader.h50
-rw-r--r--skin/PM3.HD/media/Makefile6
-rw-r--r--skin/Project Mayhem III/media/Makefile6
-rw-r--r--tools/XBMCTexXBT/Makefile17
-rw-r--r--tools/XBMCTexXBT/SDL_anigif.c776
-rw-r--r--tools/XBMCTexXBT/SDL_anigif.h62
-rw-r--r--tools/XBMCTexXBT/XBMCTex.cpp321
-rw-r--r--tools/XBMCTexXBT/XBTFWriter.cpp133
-rw-r--r--tools/XBMCTexXBT/XBTFWriter.h24
-rw-r--r--tools/XBMCTexXBT/cmdlineargs.h123
-rw-r--r--tools/XBMCTexXBT/xwinapi.cpp81
-rw-r--r--tools/XBMCTexXBT/xwinapi.h11
-rw-r--r--xbmc/Picture.cpp2
-rw-r--r--xbmc/RenderSystem.h1
-rw-r--r--xbmc/RenderSystemDX.h1
-rw-r--r--xbmc/RenderSystemGL.cpp7
-rw-r--r--xbmc/RenderSystemGL.h1
-rw-r--r--xbmc/karaoke/karaokelyricscdg.cpp2
37 files changed, 3240 insertions, 522 deletions
diff --git a/Makefile.in b/Makefile.in
index 89b6fa9862..843d147b6b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -40,6 +40,7 @@ BIN_DIRS= \
xbmc/lib/libXDAAP \
xbmc/lib/sqLite \
xbmc/lib/UnrarXLib \
+ xbmc/lib/libsquish \
xbmc/visualizations \
xbmc/screensavers \
xbmc/utils \
@@ -52,7 +53,8 @@ EC_DIRS= \
tools/EventClients
XBMCTEX_DIRS= \
- tools/XBMCTex
+ tools/XBMCTex \
+ tools/XBMCTexXBT
DVDPCODECS_DIRS= \
xbmc/cores/dvdplayer/Codecs \
@@ -181,7 +183,7 @@ configure: configure.in
@false
# skin textures
-skins: tools/XBMCTex/XBMCTex force
+skins: tools/XBMCTex/XBMCTex tools/XBMCTexXBT/XBMCTexXBT force
$(MAKE) -C $(PM3_MEDIA)
$(MAKE) -C $(PM3HD_MEDIA)
@@ -265,6 +267,8 @@ xbmc/lib/sqLite/sqllite.a: force
$(MAKE) -C xbmc/lib/sqLite
xbmc/lib/UnrarXLib/UnrarXLib.a: force
$(MAKE) -C xbmc/lib/UnrarXLib
+xbmc/lib/libsquish/libsquish.a: force
+ $(MAKE) -C xbmc/lib/libsquish
xbmc/linux/linux.a: force
$(MAKE) -C xbmc/linux
xbmc/screensavers/screensaver.a: force
@@ -401,6 +405,7 @@ OBJSXBMC= \
xbmc/lib/libGoAhead/libGoAhead-@ARCH@.a \
xbmc/lib/sqLite/sqllite.a \
xbmc/lib/UnrarXLib/UnrarXLib.a \
+ xbmc/lib/libsquish/libsquish.a \
xbmc/linux/linux.a \
xbmc/screensavers/screensaver.a \
xbmc/settings/settings.a \
@@ -449,9 +454,12 @@ ifeq ($(findstring osx,$(ARCH)), osx)
# hack this for now
$(MAKE) -C tools/XBMCTex -f Makefile.osx
else
- $(MAKE) -C tools/XBMCTex/
+ $(MAKE) -C tools/XBMCTex/
endif
+tools/XBMCTexXBT/XBMCTexXBT:
+ $(MAKE) -C tools/XBMCTexXBT/
+
install-bin: xbmc.bin # developement convenience target
sudo install -D xbmc.bin $(prefix)/share/xbmc
diff --git a/guilib/DirectXGraphics.cpp b/guilib/DirectXGraphics.cpp
index 5563b51304..3a3d107c46 100644
--- a/guilib/DirectXGraphics.cpp
+++ b/guilib/DirectXGraphics.cpp
@@ -22,6 +22,7 @@
#include "DirectXGraphics.h"
#include "Texture.h"
#include "FileSystem/File.h"
+#include "XBTF.h"
LPVOID XPhysicalAlloc(SIZE_T s, DWORD ulPhysicalAddress, DWORD ulAlignment, DWORD flProtect)
{
@@ -394,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);
+ *ppTexture = new CTexture(width, height, 32, XB_FMT_B8G8R8A8);
if (*ppTexture)
{
@@ -446,9 +447,9 @@ void GetTextureFromData(D3DTexture *pTex, void *texData, CBaseTexture **ppTextur
}
if (IsPalettedFormat(fmt))
- (*ppTexture)->LoadPaletted(width, height, pitch, texDataStart, color);
+ (*ppTexture)->LoadPaletted(width, height, pitch, XB_FMT_B8G8R8A8, texDataStart, color);
else
- (*ppTexture)->LoadFromMemory(width, height, pitch, 32, texDataStart);
+ (*ppTexture)->LoadFromMemory(width, height, pitch, 32, XB_FMT_B8G8R8A8, texDataStart);
if (IsSwizzledFormat(fmt) || fmt == XB_D3DFMT_DXT1 || fmt == XB_D3DFMT_DXT2 || fmt == XB_D3DFMT_DXT4)
{
diff --git a/guilib/Makefile b/guilib/Makefile
index 78819e5a71..fd24650ca6 100644
--- a/guilib/Makefile
+++ b/guilib/Makefile
@@ -1,4 +1,4 @@
-INCLUDES=-I. -I../ -Icommon -I../xbmc -I../xbmc/cores -I../xbmc/linux -I../xbmc/utils -I/usr/include/freetype2 -I/usr/include/SDL
+INCLUDES=-I. -I../ -Icommon -I../xbmc -I../xbmc/cores -I../xbmc/linux -I../xbmc/utils -I/usr/include/freetype2 -I/usr/include/SDL -I../xbmc/lib/squish
SRCS=AnimatedGif.cpp \
AudioContext.cpp \
@@ -56,6 +56,8 @@ SRCS=AnimatedGif.cpp \
Key.cpp \
LocalizeStrings.cpp \
SkinInfo.cpp \
+ TextureBundleXPR.cpp \
+ TextureBundleXBT.cpp \
TextureBundle.cpp \
TextureManager.cpp \
VisibleEffect.cpp \
@@ -74,6 +76,8 @@ SRCS=AnimatedGif.cpp \
Texture.cpp \
TextureGL.cpp \
GUIControlProfiler.cpp \
+ XBTF.cpp \
+ XBTFReader.cpp \
LIB=guilib.a
diff --git a/guilib/Texture.cpp b/guilib/Texture.cpp
index 0f78d6b083..d4e96d642a 100644
--- a/guilib/Texture.cpp
+++ b/guilib/Texture.cpp
@@ -30,7 +30,7 @@
/************************************************************************/
/* */
/************************************************************************/
-CBaseTexture::CBaseTexture(unsigned int width, unsigned int height, unsigned int BPP)
+CBaseTexture::CBaseTexture(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format)
{
m_imageWidth = width;
m_imageHeight = height;
@@ -40,6 +40,7 @@ CBaseTexture::CBaseTexture(unsigned int width, unsigned int height, unsigned int
m_loadedToGPU = false;
m_nTextureHeight = 0;
m_nTextureWidth = 0;
+ m_format = format;
}
CBaseTexture::~CBaseTexture()
@@ -47,13 +48,14 @@ CBaseTexture::~CBaseTexture()
delete[] m_pPixels;
}
-void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned int BPP)
+void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format)
{
if (BPP != 0)
m_nBPP = BPP;
m_imageWidth = width;
m_imageHeight = height;
+ m_format = format;
if (g_Windowing.NeedPower2Texture())
{
@@ -67,40 +69,62 @@ void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned in
}
delete[] m_pPixels;
- m_pPixels = new unsigned char[m_nTextureWidth * m_nTextureHeight * m_nBPP / 8];
+
+ 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;
+ }
+
+ m_pPixels = new unsigned char[m_bufferSize];
}
-void CBaseTexture::Update(int w, int h, int pitch, const unsigned char *pixels, bool loadToGPU)
+void CBaseTexture::Update(int w, int h, int pitch, unsigned int format, const unsigned char *pixels, bool loadToGPU)
{
if (pixels == NULL)
return;
- Allocate(w, h, 0);
+ Allocate(w, h, 0, format);
- // Resize texture to POT if needed
- const unsigned char *src = pixels;
- unsigned char* resized = m_pPixels;
-
- for (int y = 0; y < h; y++)
+ if (m_imageHeight != m_nTextureHeight && m_imageWidth != m_nTextureWidth)
{
- 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);
+ // Resize texture to POT if needed
+ const unsigned char *src = pixels;
+ unsigned char* resized = m_pPixels;
+
+ for (int y = 0; y < h; 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);
+ }
+
+ // clamp to edge - repeat last row
+ unsigned char *dest = m_pPixels + h*GetPitch();
+ for (unsigned int y = h; y < m_nTextureHeight; y++)
+ {
+ memcpy(dest, dest-GetPitch(), GetPitch());
+ dest += GetPitch();
+ }
}
-
- // clamp to edge - repeat last row
- unsigned char *dest = m_pPixels + h*GetPitch();
- for (unsigned int y = h; y < m_nTextureHeight; y++)
+ else
{
- memcpy(dest, dest-GetPitch(), GetPitch());
- dest += GetPitch();
+ memcpy(m_pPixels, pixels, m_bufferSize);
}
-
+
if (loadToGPU)
LoadToGPU();
}
@@ -116,22 +140,23 @@ bool CBaseTexture::LoadFromFile(const CStdString& texturePath)
return true;
}
-bool CBaseTexture::LoadFromMemory(unsigned int width, unsigned int height, unsigned int pitch, unsigned int BPP, unsigned char* pPixels)
+bool CBaseTexture::LoadFromMemory(unsigned int width, unsigned int height, unsigned int pitch, unsigned int BPP, unsigned int format, unsigned char* pPixels)
{
m_imageWidth = width;
m_imageHeight = height;
m_nBPP = BPP;
- Update(width, height, pitch, pPixels, false);
+ m_format = format;
+ Update(width, height, pitch, format, pPixels, false);
return true;
}
-bool CBaseTexture::LoadPaletted(unsigned int width, unsigned int height, unsigned int pitch, const unsigned char *pixels, const COLOR *palette)
+bool CBaseTexture::LoadPaletted(unsigned int width, unsigned int height, unsigned int pitch, unsigned int format, const unsigned char *pixels, const COLOR *palette)
{
if (pixels == NULL || palette == NULL)
return false;
- Allocate(width, height, 32);
+ Allocate(width, height, 32, format);
for (unsigned int y = 0; y < height; y++)
{
diff --git a/guilib/Texture.h b/guilib/Texture.h
index 73751efd10..d0f2152a0c 100644
--- a/guilib/Texture.h
+++ b/guilib/Texture.h
@@ -29,6 +29,7 @@
#include "gui3d.h"
#include "StdString.h"
+#include "XBTF.h"
#pragma pack(1)
struct COLOR {unsigned char b,g,r,x;}; // Windows GDI expects 4bytes per color
@@ -48,13 +49,13 @@ class CBaseTexture
{
public:
- CBaseTexture(unsigned int width = 0, unsigned int height = 0, unsigned int BPP = 0);
+ CBaseTexture(unsigned int width = 0, unsigned int height = 0, unsigned int BPP = 0, unsigned int format = XB_FMT_B8G8R8A8);
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 char* pPixels);
- bool LoadPaletted(unsigned int width, unsigned int height, unsigned int pitch, const unsigned char *pixels, const COLOR *palette);
+ virtual bool LoadFromMemory(unsigned int width, unsigned int height, unsigned int pitch, unsigned int BPP, unsigned int format, unsigned char* pPixels);
+ 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;
@@ -69,8 +70,8 @@ public:
unsigned int GetHeight() const { return m_imageHeight; }
unsigned int GetBPP() const { return m_nBPP; }
- void Update(int w, int h, int pitch, const unsigned char *pixels, bool loadToGPU);
- void Allocate(unsigned int width, unsigned int height, unsigned int BPP);
+ 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);
static unsigned int PadPow2(unsigned int x);
@@ -82,7 +83,9 @@ protected:
unsigned int m_nBPP;
XBMC::TexturePtr m_pTexture;
unsigned char* m_pPixels;
+ unsigned int m_bufferSize;
bool m_loadedToGPU;
+ unsigned int m_format;
};
#if defined(HAS_GL) || defined(HAS_GLES)
diff --git a/guilib/TextureBundle.cpp b/guilib/TextureBundle.cpp
index 7f025a4ac6..a3a38aeef1 100644
--- a/guilib/TextureBundle.cpp
+++ b/guilib/TextureBundle.cpp
@@ -1,487 +1,128 @@
-
+/*
+ * Copyright (C) 2005-2009 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
#include "system.h"
#include "TextureBundle.h"
-#include "Texture.h"
-#include "GraphicContext.h"
-#include "DirectXGraphics.h"
-#include "utils/log.h"
-#ifndef _LINUX
-#include <sys/stat.h>
-#include "utils/CharsetConverter.h"
-#include "lib/liblzo/LZO1X.H"
-#else
-#include <lzo/lzo1x.h>
-#endif
-#include "SkinInfo.h"
-#include "GUISettings.h"
-#include "Util.h"
-#include "FileSystem/SpecialProtocol.h"
-#include "utils/EndianSwap.h"
-
-#if !defined(__GNUC__)
-#pragma comment(lib,"../../xbmc/lib/liblzo/lzo.lib")
-#endif
-
-// alignment of file blocks - should be a multiple of the sector size of the disk and a power of 2
-// HDD sector = 512 bytes, DVD/CD sector = 2048 bytes
-#undef ALIGN
-#define ALIGN (512)
-
-
-enum XPR_FLAGS
-{
- XPRFLAG_PALETTE = 0x00000001,
- XPRFLAG_ANIM = 0x00000002
-};
-
-class CAutoBuffer
-{
- BYTE* p;
-public:
- CAutoBuffer() { p = 0; }
- explicit CAutoBuffer(size_t s) { p = (BYTE*)malloc(s); }
- ~CAutoBuffer() { free(p); }
-operator BYTE*() { return p; }
- void Set(BYTE* buf) { free(p); p = buf; }
- bool Resize(size_t s);
-void Release() { p = 0; }
-};
-
-bool CAutoBuffer::Resize(size_t s)
-{
- if (s == 0)
- {
- if (!p)
- return false;
- free(p);
- p = 0;
- return true;
- }
- void* q = realloc(p, s);
- if (q)
- {
- p = (BYTE*)q;
- return true;
- }
- return false;
-}
-
-// as above but for texture allocation (do not change from XPhysicalAlloc!)
-class CAutoTexBuffer
-{
- BYTE* p;
-public:
- CAutoTexBuffer() { p = 0; }
- explicit CAutoTexBuffer(size_t s) { p = (BYTE*)XPhysicalAlloc(s, MAXULONG_PTR, 128, PAGE_READWRITE); }
- ~CAutoTexBuffer() { if (p) XPhysicalFree(p); }
-operator BYTE*() { return p; }
- BYTE* Set(BYTE* buf) { if (p) XPhysicalFree(p); return p = buf; }
-void Release() { p = 0; }
-};
CTextureBundle::CTextureBundle(void)
{
- m_hFile = NULL;
- m_themeBundle = false;
+ m_useXPR = false;
+ m_useXBT = false;
}
CTextureBundle::~CTextureBundle(void)
{
- if (m_hFile != NULL)
- fclose(m_hFile);
}
-bool CTextureBundle::OpenBundle()
+bool CTextureBundle::HasFile(const CStdString& Filename)
{
- DWORD AlignedSize;
- DWORD HeaderSize;
- int Version;
- XPR_HEADER* pXPRHeader;
-
- if (m_hFile != NULL)
- Cleanup();
-
- CStdString strPath;
-
- if (m_themeBundle)
+ if (m_useXBT)
{
- // if we are the theme bundle, we only load if the user has chosen
- // a valid theme (or the skin has a default one)
- CStdString themeXPR = g_guiSettings.GetString("lookandfeel.skintheme");
- if (!themeXPR.IsEmpty() && themeXPR.CompareNoCase("SKINDEFAULT"))
- {
- strPath = CUtil::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media");
- strPath = CUtil::AddFileToFolder(strPath, themeXPR);
- }
- else
- return false;
+ return m_tbXBT.HasFile(Filename);
}
- else
- strPath = CUtil::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media/Textures.xpr");
-
- strPath = PTH_IC(strPath);
-
-#ifndef _LINUX
- CStdStringW strPathW;
- g_charsetConverter.utf8ToW(_P(strPath), strPathW, false);
- m_hFile = _wfopen(strPathW.c_str(), L"rb");
-#else
- m_hFile = fopen(strPath.c_str(), "rb");
-#endif
- if (m_hFile == NULL)
- return false;
-
- struct stat fileStat;
- if (fstat(fileno(m_hFile), &fileStat) == -1)
- return false;
- m_TimeStamp = fileStat.st_mtime;
-
- CAutoBuffer HeaderBuf(ALIGN);
- DWORD n;
-
- n = fread(HeaderBuf, 1, ALIGN, m_hFile);
- if (n < ALIGN)
- goto LoadError;
-
- pXPRHeader = (XPR_HEADER*)(BYTE*)HeaderBuf;
- pXPRHeader->dwMagic = Endian_SwapLE32(pXPRHeader->dwMagic);
- Version = (pXPRHeader->dwMagic >> 24) - '0';
- pXPRHeader->dwMagic -= Version << 24;
- Version &= 0x0f;
-
- if (pXPRHeader->dwMagic != XPR_MAGIC_VALUE || Version < 2)
- goto LoadError;
-
- HeaderSize = Endian_SwapLE32(pXPRHeader->dwHeaderSize);
- AlignedSize = (HeaderSize - 1) & ~(ALIGN - 1); // align to sector, but remove the first sector
- HeaderBuf.Resize(AlignedSize + ALIGN);
-
- if (fseek(m_hFile, ALIGN, SEEK_SET) == -1)
- goto LoadError;
- n = fread(HeaderBuf + ALIGN, 1, AlignedSize, m_hFile);
- if (n < ALIGN)
- goto LoadError;
-
- struct DiskFileHeader_t
+ else if (m_useXPR)
{
- char Name[116];
- DWORD Offset;
- DWORD UnpackedSize;
- DWORD PackedSize;
+ return m_tbXPR.HasFile(Filename);
}
- *FileHeader;
- FileHeader = (DiskFileHeader_t*)(HeaderBuf + sizeof(XPR_HEADER));
-
- n = (HeaderSize - sizeof(XPR_HEADER)) / sizeof(DiskFileHeader_t);
- for (unsigned i = 0; i < n; ++i)
+ else if (m_tbXBT.HasFile(Filename))
+ {
+ m_useXBT = true;
+ return true;
+ }
+ else if (m_tbXPR.HasFile(Filename))
{
- std::pair<CStdString, FileHeader_t> entry;
- entry.first = Normalize(FileHeader[i].Name);
- entry.second.Offset = Endian_SwapLE32(FileHeader[i].Offset);
- entry.second.UnpackedSize = Endian_SwapLE32(FileHeader[i].UnpackedSize);
- entry.second.PackedSize = Endian_SwapLE32(FileHeader[i].PackedSize);
- m_FileHeaders.insert(entry);
+ m_useXPR = true;
+ return true;
}
-
- if (lzo_init() != LZO_E_OK)
- goto LoadError;
-
- return true;
-
-LoadError:
- CLog::Log(LOGERROR, "Unable to load file: %s: %s", strPath.c_str(), strerror(errno));
- fclose(m_hFile);
- m_hFile = NULL;
-
- return false;
-}
-
-void CTextureBundle::Cleanup()
-{
- if (m_hFile != NULL)
- fclose(m_hFile);
- m_hFile = NULL;
-
- m_FileHeaders.clear();
-}
-
-bool CTextureBundle::HasFile(const CStdString& Filename)
-{
- if (m_hFile == NULL && !OpenBundle())
- return false;
-
- struct stat fileStat;
- if (fstat(fileno(m_hFile), &fileStat) == -1)
- return false;
- if (fileStat.st_mtime > m_TimeStamp)
+ else
{
- CLog::Log(LOGINFO, "Texture bundle has changed, reloading");
- Cleanup();
- if (!OpenBundle())
- return false;
+ return false;
}
-
- CStdString name = Normalize(Filename);
- return m_FileHeaders.find(name) != m_FileHeaders.end();
}
void CTextureBundle::GetTexturesFromPath(const CStdString &path, std::vector<CStdString> &textures)
{
- if (path.GetLength() > 1 && path[1] == ':')
- return;
-
- if (m_hFile == NULL && !OpenBundle())
- return;
-
- CStdString testPath = Normalize(path);
- if (!CUtil::HasSlashAtEnd(testPath))
- testPath += "\\";
- int testLength = testPath.GetLength();
- std::map<CStdString, FileHeader_t>::iterator it;
- for (it = m_FileHeaders.begin(); it != m_FileHeaders.end(); it++)
+ if (m_useXBT)
{
- if (it->first.Left(testLength).Equals(testPath))
- textures.push_back(it->first);
+ m_tbXBT.GetTexturesFromPath(path, textures);
}
+ else if (m_useXPR)
+ {
+ m_tbXPR.GetTexturesFromPath(path, textures);
+ }
}
-bool CTextureBundle::LoadFile(const CStdString& Filename, CAutoTexBuffer& UnpackedBuf)
+bool CTextureBundle::LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture,
+ int &width, int &height)
{
- CStdString name = Normalize(Filename);
-
- std::map<CStdString, FileHeader_t>::iterator file = m_FileHeaders.find(name);
- if (file == m_FileHeaders.end())
- return false;
-
- // found texture - allocate the necessary buffers
- DWORD ReadSize = (file->second.PackedSize + (ALIGN - 1)) & ~(ALIGN - 1);
- BYTE *buffer = (BYTE*)malloc(ReadSize);
-
- if (!buffer || !UnpackedBuf.Set((BYTE*)XPhysicalAlloc(file->second.UnpackedSize, MAXULONG_PTR, 128, PAGE_READWRITE)))
- { // failed due to lack of memory
-#ifndef _LINUX
- MEMORYSTATUS stat;
- GlobalMemoryStatus(&stat);
- CLog::Log(LOGERROR, "Out of memory loading texture: %s (need %lu bytes, have %lu bytes)", name.c_str(),
- file->second.UnpackedSize + file->second.PackedSize, stat.dwAvailPhys);
-#elif defined(__APPLE__)
- CLog::Log(LOGERROR, "Out of memory loading texture: %s (need %lu bytes)", name.c_str(),
- file->second.UnpackedSize + file->second.PackedSize);
-#else
- struct sysinfo info;
- sysinfo(&info);
- CLog::Log(LOGERROR, "Out of memory loading texture: %s "
- "(need %u bytes, have %lu bytes)",
- name.c_str(), file->second.UnpackedSize + file->second.PackedSize,
- info.totalram);
-#endif
- free(buffer);
- return false;
- }
-
- // read the file into our buffer
- DWORD n;
- fseek(m_hFile, file->second.Offset, SEEK_SET);
- n = fread(buffer, 1, ReadSize, m_hFile);
- if (n < ReadSize && !feof(m_hFile))
+ if (m_useXBT)
{
- CLog::Log(LOGERROR, "Error loading texture: %s: %s", Filename.c_str(), strerror(ferror(m_hFile)));
- free(buffer);
- return false;
- }
-
- // allocate a buffer for our unpacked texture
- lzo_uint s = file->second.UnpackedSize;
- bool success = true;
- if (lzo1x_decompress(buffer, file->second.PackedSize, UnpackedBuf, &s, NULL) != LZO_E_OK ||
- s != file->second.UnpackedSize)
- {
- CLog::Log(LOGERROR, "Error loading texture: %s: Decompression error", Filename.c_str());
- success = false;
+ return m_tbXBT.LoadTexture(Filename, ppTexture, width, height);
}
-
- try
+ else if (m_useXPR)
{
- free(buffer);
+ return m_tbXPR.LoadTexture(Filename, ppTexture, width, height);
}
- catch (...)
+ else
{
- CLog::Log(LOGERROR, "Error freeing preload buffer.");
- }
-
- return success;
-}
-
-bool CTextureBundle::LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture,
- int &width, int &height)
-{
- DWORD ResDataOffset;
- *ppTexture = NULL;
-
- CAutoTexBuffer UnpackedBuf;
- if (!LoadFile(Filename, UnpackedBuf))
return false;
-
- D3DTexture *pTex = (D3DTexture *)(new char[sizeof (D3DTexture)]);
- D3DPalette* pPal = 0;
- void* ResData = 0;
-
- WORD RealSize[2];
-
- enum XPR_FLAGS
- {
- XPRFLAG_PALETTE = 0x00000001,
- XPRFLAG_ANIM = 0x00000002
- };
-
- BYTE* Next = UnpackedBuf;
-
- DWORD flags = Endian_SwapLE32(*(DWORD*)Next);
- Next += sizeof(DWORD);
- if ((flags & XPRFLAG_ANIM) || (flags >> 16) > 1)
- goto PackedLoadError;
-
- if (flags & XPRFLAG_PALETTE)
- Next += sizeof(D3DPalette);
-
- memcpy(pTex, Next, sizeof(D3DTexture));
- pTex->Common = Endian_SwapLE32(pTex->Common);
- pTex->Data = Endian_SwapLE32(pTex->Data);
- pTex->Lock = Endian_SwapLE32(pTex->Lock);
- pTex->Format = Endian_SwapLE32(pTex->Format);
- pTex->Size = Endian_SwapLE32(pTex->Size);
- Next += sizeof(D3DTexture);
-
- memcpy(RealSize, Next, 4);
- Next += 4;
-
- ResDataOffset = ((Next - UnpackedBuf) + 127) & ~127;
- ResData = UnpackedBuf + ResDataOffset;
-
- if ((pTex->Common & D3DCOMMON_TYPE_MASK) != D3DCOMMON_TYPE_TEXTURE)
- goto PackedLoadError;
-
- GetTextureFromData(pTex, ResData, ppTexture);
- delete[] pTex;
-
- width = Endian_SwapLE16(RealSize[0]);
- height = Endian_SwapLE16(RealSize[1]);
-/* DXMERGE - this was previously used to specify the format of the image - probably only affects directx?
-#ifndef HAS_SDL
- D3DSURFACE_DESC desc;
- (*ppTexture)->GetLevelDesc(0, &desc);
- pInfo->Format = desc.Format;
-#endif
-*/
- return true;
-
-PackedLoadError:
- CLog::Log(LOGERROR, "Error loading texture: %s: Invalid data", Filename.c_str());
- delete[] pTex;
- delete pPal;
- return false;
+ }
}
int CTextureBundle::LoadAnim(const CStdString& Filename, CBaseTexture*** ppTextures,
int &width, int &height, int& nLoops, int** ppDelays)
{
- DWORD ResDataOffset;
- int nTextures = 0;
-
- *ppTextures = NULL; *ppDelays = NULL;
-
- CAutoTexBuffer UnpackedBuf;
- if (!LoadFile(Filename, UnpackedBuf))
- return 0;
-
- struct AnimInfo_t
+ if (m_useXBT)
{
- DWORD nLoops;
- WORD RealSize[2];
+ return m_tbXBT.LoadAnim(Filename, ppTextures, width, height, nLoops, ppDelays);
}
- *pAnimInfo;
-
- D3DTexture** ppTex = 0;
- void* ResData = 0;
-
- BYTE* Next = UnpackedBuf;
-
- DWORD flags = Endian_SwapLE32(*(DWORD*)Next);
- Next += sizeof(DWORD);
- if (!(flags & XPRFLAG_ANIM))
- goto PackedAnimError;
-
- pAnimInfo = (AnimInfo_t*)Next;
- Next += sizeof(AnimInfo_t);
- nLoops = Endian_SwapLE32(pAnimInfo->nLoops);
-
- if (flags & XPRFLAG_PALETTE)
- Next += sizeof(D3DPalette);
-
- nTextures = flags >> 16;
- ppTex = new D3DTexture * [nTextures];
- *ppDelays = new int[nTextures];
- for (int i = 0; i < nTextures; ++i)
+ else if (m_useXPR)
{
- ppTex[i] = (D3DTexture *)(new char[sizeof (D3DTexture)+ sizeof (DWORD)]);
-
- memcpy(ppTex[i], Next, sizeof(D3DTexture));
- ppTex[i]->Common = Endian_SwapLE32(ppTex[i]->Common);
- ppTex[i]->Data = Endian_SwapLE32(ppTex[i]->Data);
- ppTex[i]->Lock = Endian_SwapLE32(ppTex[i]->Lock);
- ppTex[i]->Format = Endian_SwapLE32(ppTex[i]->Format);
- ppTex[i]->Size = Endian_SwapLE32(ppTex[i]->Size);
- Next += sizeof(D3DTexture);
-
- (*ppDelays)[i] = Endian_SwapLE32(*(int*)Next);
- Next += sizeof(int);
+ return m_tbXPR.LoadAnim(Filename, ppTextures, width, height, nLoops, ppDelays);
}
-
- ResDataOffset = ((DWORD)(Next - UnpackedBuf) + 127) & ~127;
- ResData = UnpackedBuf + ResDataOffset;
-
- *ppTextures = new CBaseTexture*[nTextures];
- for (int i = 0; i < nTextures; ++i)
+ else
{
- if ((ppTex[i]->Common & D3DCOMMON_TYPE_MASK) != D3DCOMMON_TYPE_TEXTURE)
- goto PackedAnimError;
+ return 0;
+ }
+}
- GetTextureFromData(ppTex[i], ResData, &(*ppTextures)[i]);
- delete[] ppTex[i];
+void CTextureBundle::Cleanup()
+{
+ if (m_useXBT)
+ {
+ m_tbXBT.Cleanup();
}
-
- delete[] ppTex;
- ppTex = 0;
-
- width = Endian_SwapLE16(pAnimInfo->RealSize[0]);
- height = Endian_SwapLE16(pAnimInfo->RealSize[1]);
-
- return nTextures;
-
-PackedAnimError:
- CLog::Log(LOGERROR, "Error loading texture: %s: Invalid data", Filename.c_str());
- if (ppTex)
+ else if (m_useXPR)
{
- for (int i = 0; i < nTextures; ++i)
- delete [] ppTex[i];
- delete [] ppTex;
+ m_tbXPR.Cleanup();
}
- delete [] *ppDelays;
- return 0;
}
-
+
void CTextureBundle::SetThemeBundle(bool themeBundle)
{
- m_themeBundle = themeBundle;
+ m_tbXPR.SetThemeBundle(themeBundle);
+ m_tbXBT.SetThemeBundle(themeBundle);
}
-// normalize to how it's stored within the bundle
-// lower case + using \\ rather than /
CStdString CTextureBundle::Normalize(const CStdString &name)
{
- CStdString newName(name);
- newName.Normalize();
- newName.Replace('/','\\');
- return newName;
+ return CTextureBundleXBT::Normalize(name);
}
diff --git a/guilib/TextureBundle.h b/guilib/TextureBundle.h
index 5ae9aebca0..d9584dd5f8 100644
--- a/guilib/TextureBundle.h
+++ b/guilib/TextureBundle.h
@@ -22,32 +22,11 @@
*/
#include "StdString.h"
-#include <stdint.h>
-#include <map>
-
-class CAutoTexBuffer;
-class CBaseTexture;
+#include "TextureBundleXPR.h"
+#include "TextureBundleXBT.h"
class CTextureBundle
{
- struct FileHeader_t
- {
- uint32_t Offset;
- uint32_t UnpackedSize;
- uint32_t PackedSize;
- };
-
- FILE* m_hFile;
- time_t m_TimeStamp;
-
- std::map<CStdString, FileHeader_t> m_FileHeaders;
- typedef std::map<CStdString, FileHeader_t>::iterator iFiles;
-
- bool m_themeBundle;
-
- bool OpenBundle();
- bool LoadFile(const CStdString& Filename, CAutoTexBuffer& UnpackedBuf);
-
public:
CTextureBundle(void);
~CTextureBundle(void);
@@ -59,11 +38,16 @@ public:
void GetTexturesFromPath(const CStdString &path, std::vector<CStdString> &textures);
static CStdString Normalize(const CStdString &name);
- bool LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture,
- int &width, int &height);
+ bool LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture, int &width, int &height);
- int LoadAnim(const CStdString& Filename, CBaseTexture*** ppTextures,
- int &width, int &height, int& nLoops, int** ppDelays);
+ int LoadAnim(const CStdString& Filename, CBaseTexture*** ppTextures, int &width, int &height, int& nLoops, int** ppDelays);
+
+private:
+ CTextureBundleXPR m_tbXPR;
+ CTextureBundleXBT m_tbXBT;
+
+ bool m_useXPR;
+ bool m_useXBT;
};
diff --git a/guilib/TextureBundleXBT.cpp b/guilib/TextureBundleXBT.cpp
new file mode 100644
index 0000000000..8e10e5b631
--- /dev/null
+++ b/guilib/TextureBundleXBT.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2005-2009 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "squish.h"
+#include "system.h"
+#include "TextureBundleXBT.h"
+#include "Texture.h"
+#include "GraphicContext.h"
+#include "utils/log.h"
+#include "SkinInfo.h"
+#include "GUISettings.h"
+#include "Util.h"
+#include "FileSystem/SpecialProtocol.h"
+#include "utils/EndianSwap.h"
+#include "XBTF.h"
+#include "WindowingFactory.h"
+#ifndef _LINUX
+#include "lib/liblzo/LZO1X.H"
+#else
+#include <lzo/lzo1x.h>
+#endif
+
+#if !defined(__GNUC__)
+#pragma comment(lib,"../../xbmc/lib/liblzo/lzo.lib")
+#endif
+
+CTextureBundleXBT::CTextureBundleXBT(void)
+{
+ m_themeBundle = false;
+}
+
+CTextureBundleXBT::~CTextureBundleXBT(void)
+{
+ Cleanup();
+}
+
+bool CTextureBundleXBT::OpenBundle()
+{
+ m_supportsCompressedTextures = g_Windowing.SupportsCompressedTextures();
+
+ Cleanup();
+
+ // Find the correct texture file (skin or theme)
+ CStdString strPath;
+
+ if (m_themeBundle)
+ {
+ // if we are the theme bundle, we only load if the user has chosen
+ // a valid theme (or the skin has a default one)
+ CStdString themeXPR = g_guiSettings.GetString("lookandfeel.skintheme");
+ if (!themeXPR.IsEmpty() && themeXPR.Find(".xbt") != -1 && themeXPR.CompareNoCase("SKINDEFAULT"))
+ {
+ strPath = CUtil::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media");
+ strPath = CUtil::AddFileToFolder(strPath, themeXPR);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ strPath = CUtil::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media/Textures.xbt");
+ }
+
+ strPath = PTH_IC(strPath);
+
+ // Load the texture file
+ if (!m_XBTFReader.Open(strPath))
+ {
+ return false;
+ }
+
+ m_TimeStamp = m_XBTFReader.GetLastModificationTimestamp();
+
+ if (lzo_init() != LZO_E_OK)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool CTextureBundleXBT::HasFile(const CStdString& Filename)
+{
+ if (!m_XBTFReader.IsOpen() && !OpenBundle())
+ return false;
+
+ if (m_XBTFReader.GetLastModificationTimestamp() > m_TimeStamp)
+ {
+ CLog::Log(LOGINFO, "Texture bundle has changed, reloading");
+ if (!OpenBundle())
+ return false;
+ }
+
+ CStdString name = Normalize(Filename);
+ bool result = m_XBTFReader.Exists(name, XB_FMT_DXT5);
+ return result;
+}
+
+void CTextureBundleXBT::GetTexturesFromPath(const CStdString &path, std::vector<CStdString> &textures)
+{
+ if (path.GetLength() > 1 && path[1] == ':')
+ return;
+
+ if (!m_XBTFReader.IsOpen() && !OpenBundle())
+ return;
+
+ CStdString testPath = Normalize(path);
+ CUtil::AddSlashAtEnd(testPath);
+ int testLength = testPath.GetLength();
+
+ std::vector<CXBTFFile>& files = m_XBTFReader.GetFiles();
+ for (size_t i = 0; i < files.size(); i++)
+ {
+ CStdString path = files[i].GetPath();
+ if (path.Left(testLength).Equals(testPath))
+ textures.push_back(path);
+ }
+}
+
+bool CTextureBundleXBT::LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture,
+ int &width, int &height)
+{
+ CStdString name = Normalize(Filename);
+
+ CXBTFFile* file = m_XBTFReader.Find(name, XB_FMT_DXT5);
+ if (!file)
+ return false;
+
+ if (file->GetFrames().size() == 0)
+ return false;
+
+ CXBTFFrame& frame = file->GetFrames().at(0);
+ if (!ConvertFrameToTexture(Filename, frame, file->GetFormat(), ppTexture))
+ {
+ return false;
+ }
+
+ width = frame.GetWidth();
+ height = frame.GetHeight();
+
+ return true;
+}
+
+int CTextureBundleXBT::LoadAnim(const CStdString& Filename, CBaseTexture*** ppTextures,
+ int &width, int &height, int& nLoops, int** ppDelays)
+{
+ CStdString name = Normalize(Filename);
+
+ CXBTFFile* file = m_XBTFReader.Find(name, XB_FMT_DXT5);
+ if (!file)
+ return false;
+
+ if (file->GetFrames().size() == 0)
+ return false;
+
+ size_t nTextures = file->GetFrames().size();
+ *ppTextures = new CBaseTexture*[nTextures];
+ *ppDelays = new int[nTextures];
+
+ for (size_t i = 0; i < nTextures; i++)
+ {
+ CXBTFFrame& frame = file->GetFrames().at(i);
+
+ if (!ConvertFrameToTexture(Filename, frame, file->GetFormat(), &((*ppTextures)[i])))
+ {
+ return false;
+ }
+
+ (*ppDelays)[i] = frame.GetDuration();
+ }
+
+ width = file->GetFrames().at(0).GetWidth();
+ height = file->GetFrames().at(0).GetHeight();
+ nLoops = file->GetLoop();
+
+ return nTextures;
+}
+
+bool CTextureBundleXBT::ConvertFrameToTexture(const CStdString& name, CXBTFFrame& frame, int format, CBaseTexture** ppTexture)
+{
+ // found texture - allocate the necessary buffers
+ unsigned char* PackedBuf = (unsigned char*) malloc(frame.GetPackedSize());
+ if (PackedBuf == 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))
+ {
+ CLog::Log(LOGERROR, "Error loading texture: %s", name.c_str());
+ free(PackedBuf);
+ 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)
+ {
+ CLog::Log(LOGERROR, "Out of memory unpacking texture: %s (need %llu bytes)", name.c_str(), frame.GetUnpackedSize());
+ free(PackedBuf);
+ return false;
+ }
+
+ if (format == XB_FMT_LZO)
+ {
+ lzo_uint s = frame.GetUnpackedSize();
+ if (lzo1x_decompress(PackedBuf, 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;
+ }
+ }
+ else
+ {
+ squish::DecompressImage(UnpackedBuf, frame.GetWidth(), frame.GetHeight(), (const squish::u8*) PackedBuf, squish::kDxt5);
+ }
+
+ format = XB_FMT_R8G8B8A8;
+ }
+
+ // 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);
+
+ free(PackedBuf);
+ if (UnpackedBuf)
+ delete [] UnpackedBuf;
+
+ return true;
+}
+
+void CTextureBundleXBT::Cleanup()
+{
+ if (m_XBTFReader.IsOpen())
+ {
+ m_XBTFReader.Close();
+ }
+}
+
+void CTextureBundleXBT::SetThemeBundle(bool themeBundle)
+{
+ m_themeBundle = themeBundle;
+}
+
+// normalize to how it's stored within the bundle
+// lower case + using forward slash rather than back slash
+CStdString CTextureBundleXBT::Normalize(const CStdString &name)
+{
+ CStdString newName(name);
+ newName.Normalize();
+ newName.Replace('\\','/');
+
+ return newName;
+}
diff --git a/guilib/TextureBundleXBT.h b/guilib/TextureBundleXBT.h
new file mode 100644
index 0000000000..a5f1d7a3b8
--- /dev/null
+++ b/guilib/TextureBundleXBT.h
@@ -0,0 +1,59 @@
+#pragma once
+
+/*
+ * Copyright (C) 2005-2008 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "StdString.h"
+#include <map>
+#include "XBTFReader.h"
+
+class CBaseTexture;
+
+class CTextureBundleXBT
+{
+public:
+ CTextureBundleXBT(void);
+ ~CTextureBundleXBT(void);
+
+ void Cleanup();
+ void SetThemeBundle(bool themeBundle);
+ bool HasFile(const CStdString& Filename);
+ void GetTexturesFromPath(const CStdString &path, std::vector<CStdString> &textures);
+ static CStdString Normalize(const CStdString &name);
+
+ bool LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture,
+ int &width, int &height);
+
+ int LoadAnim(const CStdString& Filename, CBaseTexture*** ppTextures,
+ int &width, int &height, int& nLoops, int** ppDelays);
+
+private:
+ bool OpenBundle();
+ bool ConvertFrameToTexture(const CStdString& name, CXBTFFrame& frame, int format, CBaseTexture** ppTexture);
+
+ time_t m_TimeStamp;
+
+ bool m_themeBundle;
+ bool m_supportsCompressedTextures;
+ CXBTFReader m_XBTFReader;
+};
+
+
diff --git a/guilib/TextureBundleXPR.cpp b/guilib/TextureBundleXPR.cpp
new file mode 100644
index 0000000000..69d7462b7c
--- /dev/null
+++ b/guilib/TextureBundleXPR.cpp
@@ -0,0 +1,487 @@
+
+
+#include "system.h"
+#include "TextureBundleXPR.h"
+#include "Texture.h"
+#include "GraphicContext.h"
+#include "DirectXGraphics.h"
+#include "utils/log.h"
+#ifndef _LINUX
+#include <sys/stat.h>
+#include "utils/CharsetConverter.h"
+#include "lib/liblzo/LZO1X.H"
+#else
+#include <lzo/lzo1x.h>
+#endif
+#include "SkinInfo.h"
+#include "GUISettings.h"
+#include "Util.h"
+#include "FileSystem/SpecialProtocol.h"
+#include "utils/EndianSwap.h"
+
+#if !defined(__GNUC__)
+#pragma comment(lib,"../../xbmc/lib/liblzo/lzo.lib")
+#endif
+
+// alignment of file blocks - should be a multiple of the sector size of the disk and a power of 2
+// HDD sector = 512 bytes, DVD/CD sector = 2048 bytes
+#undef ALIGN
+#define ALIGN (512)
+
+
+enum XPR_FLAGS
+{
+ XPRFLAG_PALETTE = 0x00000001,
+ XPRFLAG_ANIM = 0x00000002
+};
+
+class CAutoBuffer
+{
+ BYTE* p;
+public:
+ CAutoBuffer() { p = 0; }
+ explicit CAutoBuffer(size_t s) { p = (BYTE*)malloc(s); }
+ ~CAutoBuffer() { free(p); }
+operator BYTE*() { return p; }
+ void Set(BYTE* buf) { free(p); p = buf; }
+ bool Resize(size_t s);
+void Release() { p = 0; }
+};
+
+bool CAutoBuffer::Resize(size_t s)
+{
+ if (s == 0)
+ {
+ if (!p)
+ return false;
+ free(p);
+ p = 0;
+ return true;
+ }
+ void* q = realloc(p, s);
+ if (q)
+ {
+ p = (BYTE*)q;
+ return true;
+ }
+ return false;
+}
+
+// as above but for texture allocation (do not change from XPhysicalAlloc!)
+class CAutoTexBuffer
+{
+ BYTE* p;
+public:
+ CAutoTexBuffer() { p = 0; }
+ explicit CAutoTexBuffer(size_t s) { p = (BYTE*)XPhysicalAlloc(s, MAXULONG_PTR, 128, PAGE_READWRITE); }
+ ~CAutoTexBuffer() { if (p) XPhysicalFree(p); }
+operator BYTE*() { return p; }
+ BYTE* Set(BYTE* buf) { if (p) XPhysicalFree(p); return p = buf; }
+void Release() { p = 0; }
+};
+
+CTextureBundleXPR::CTextureBundleXPR(void)
+{
+ m_hFile = NULL;
+ m_themeBundle = false;
+}
+
+CTextureBundleXPR::~CTextureBundleXPR(void)
+{
+ if (m_hFile != NULL)
+ fclose(m_hFile);
+}
+
+bool CTextureBundleXPR::OpenBundle()
+{
+ DWORD AlignedSize;
+ DWORD HeaderSize;
+ int Version;
+ XPR_HEADER* pXPRHeader;
+
+ if (m_hFile != NULL)
+ Cleanup();
+
+ CStdString strPath;
+
+ if (m_themeBundle)
+ {
+ // if we are the theme bundle, we only load if the user has chosen
+ // a valid theme (or the skin has a default one)
+ CStdString themeXPR = g_guiSettings.GetString("lookandfeel.skintheme");
+ if (!themeXPR.IsEmpty() && themeXPR.CompareNoCase("SKINDEFAULT"))
+ {
+ strPath = CUtil::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media");
+ strPath = CUtil::AddFileToFolder(strPath, themeXPR);
+ }
+ else
+ return false;
+ }
+ else
+ strPath = CUtil::AddFileToFolder(g_graphicsContext.GetMediaDir(), "media/Textures.xpr");
+
+ strPath = PTH_IC(strPath);
+
+#ifndef _LINUX
+ CStdStringW strPathW;
+ g_charsetConverter.utf8ToW(_P(strPath), strPathW, false);
+ m_hFile = _wfopen(strPathW.c_str(), L"rb");
+#else
+ m_hFile = fopen(strPath.c_str(), "rb");
+#endif
+ if (m_hFile == NULL)
+ return false;
+
+ struct stat fileStat;
+ if (fstat(fileno(m_hFile), &fileStat) == -1)
+ return false;
+ m_TimeStamp = fileStat.st_mtime;
+
+ CAutoBuffer HeaderBuf(ALIGN);
+ DWORD n;
+
+ n = fread(HeaderBuf, 1, ALIGN, m_hFile);
+ if (n < ALIGN)
+ goto LoadError;
+
+ pXPRHeader = (XPR_HEADER*)(BYTE*)HeaderBuf;
+ pXPRHeader->dwMagic = Endian_SwapLE32(pXPRHeader->dwMagic);
+ Version = (pXPRHeader->dwMagic >> 24) - '0';
+ pXPRHeader->dwMagic -= Version << 24;
+ Version &= 0x0f;
+
+ if (pXPRHeader->dwMagic != XPR_MAGIC_VALUE || Version < 2)
+ goto LoadError;
+
+ HeaderSize = Endian_SwapLE32(pXPRHeader->dwHeaderSize);
+ AlignedSize = (HeaderSize - 1) & ~(ALIGN - 1); // align to sector, but remove the first sector
+ HeaderBuf.Resize(AlignedSize + ALIGN);
+
+ if (fseek(m_hFile, ALIGN, SEEK_SET) == -1)
+ goto LoadError;
+ n = fread(HeaderBuf + ALIGN, 1, AlignedSize, m_hFile);
+ if (n < ALIGN)
+ goto LoadError;
+
+ struct DiskFileHeader_t
+ {
+ char Name[116];
+ DWORD Offset;
+ DWORD UnpackedSize;
+ DWORD PackedSize;
+ }
+ *FileHeader;
+ FileHeader = (DiskFileHeader_t*)(HeaderBuf + sizeof(XPR_HEADER));
+
+ n = (HeaderSize - sizeof(XPR_HEADER)) / sizeof(DiskFileHeader_t);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ std::pair<CStdString, FileHeader_t> entry;
+ entry.first = Normalize(FileHeader[i].Name);
+ entry.second.Offset = Endian_SwapLE32(FileHeader[i].Offset);
+ entry.second.UnpackedSize = Endian_SwapLE32(FileHeader[i].UnpackedSize);
+ entry.second.PackedSize = Endian_SwapLE32(FileHeader[i].PackedSize);
+ m_FileHeaders.insert(entry);
+ }
+
+ if (lzo_init() != LZO_E_OK)
+ goto LoadError;
+
+ return true;
+
+LoadError:
+ CLog::Log(LOGERROR, "Unable to load file: %s: %s", strPath.c_str(), strerror(errno));
+ fclose(m_hFile);
+ m_hFile = NULL;
+
+ return false;
+}
+
+void CTextureBundleXPR::Cleanup()
+{
+ if (m_hFile != NULL)
+ fclose(m_hFile);
+ m_hFile = NULL;
+
+ m_FileHeaders.clear();
+}
+
+bool CTextureBundleXPR::HasFile(const CStdString& Filename)
+{
+ if (m_hFile == NULL && !OpenBundle())
+ return false;
+
+ struct stat fileStat;
+ if (fstat(fileno(m_hFile), &fileStat) == -1)
+ return false;
+ if (fileStat.st_mtime > m_TimeStamp)
+ {
+ CLog::Log(LOGINFO, "Texture bundle has changed, reloading");
+ Cleanup();
+ if (!OpenBundle())
+ return false;
+ }
+
+ CStdString name = Normalize(Filename);
+ return m_FileHeaders.find(name) != m_FileHeaders.end();
+}
+
+void CTextureBundleXPR::GetTexturesFromPath(const CStdString &path, std::vector<CStdString> &textures)
+{
+ if (path.GetLength() > 1 && path[1] == ':')
+ return;
+
+ if (m_hFile == NULL && !OpenBundle())
+ return;
+
+ CStdString testPath = Normalize(path);
+ if (!CUtil::HasSlashAtEnd(testPath))
+ testPath += "\\";
+ int testLength = testPath.GetLength();
+ std::map<CStdString, FileHeader_t>::iterator it;
+ for (it = m_FileHeaders.begin(); it != m_FileHeaders.end(); it++)
+ {
+ if (it->first.Left(testLength).Equals(testPath))
+ textures.push_back(it->first);
+ }
+}
+
+bool CTextureBundleXPR::LoadFile(const CStdString& Filename, CAutoTexBuffer& UnpackedBuf)
+{
+ CStdString name = Normalize(Filename);
+
+ std::map<CStdString, FileHeader_t>::iterator file = m_FileHeaders.find(name);
+ if (file == m_FileHeaders.end())
+ return false;
+
+ // found texture - allocate the necessary buffers
+ DWORD ReadSize = (file->second.PackedSize + (ALIGN - 1)) & ~(ALIGN - 1);
+ BYTE *buffer = (BYTE*)malloc(ReadSize);
+
+ if (!buffer || !UnpackedBuf.Set((BYTE*)XPhysicalAlloc(file->second.UnpackedSize, MAXULONG_PTR, 128, PAGE_READWRITE)))
+ { // failed due to lack of memory
+#ifndef _LINUX
+ MEMORYSTATUS stat;
+ GlobalMemoryStatus(&stat);
+ CLog::Log(LOGERROR, "Out of memory loading texture: %s (need %lu bytes, have %lu bytes)", name.c_str(),
+ file->second.UnpackedSize + file->second.PackedSize, stat.dwAvailPhys);
+#elif defined(__APPLE__)
+ CLog::Log(LOGERROR, "Out of memory loading texture: %s (need %d bytes)", name.c_str(),
+ file->second.UnpackedSize + file->second.PackedSize);
+#else
+ struct sysinfo info;
+ sysinfo(&info);
+ CLog::Log(LOGERROR, "Out of memory loading texture: %s "
+ "(need %u bytes, have %lu bytes)",
+ name.c_str(), file->second.UnpackedSize + file->second.PackedSize,
+ info.totalram);
+#endif
+ free(buffer);
+ return false;
+ }
+
+ // read the file into our buffer
+ DWORD n;
+ fseek(m_hFile, file->second.Offset, SEEK_SET);
+ n = fread(buffer, 1, ReadSize, m_hFile);
+ if (n < ReadSize && !feof(m_hFile))
+ {
+ CLog::Log(LOGERROR, "Error loading texture: %s: %s", Filename.c_str(), strerror(ferror(m_hFile)));
+ free(buffer);
+ return false;
+ }
+
+ // allocate a buffer for our unpacked texture
+ lzo_uint s = file->second.UnpackedSize;
+ bool success = true;
+ if (lzo1x_decompress(buffer, file->second.PackedSize, UnpackedBuf, &s, NULL) != LZO_E_OK ||
+ s != file->second.UnpackedSize)
+ {
+ CLog::Log(LOGERROR, "Error loading texture: %s: Decompression error", Filename.c_str());
+ success = false;
+ }
+
+ try
+ {
+ free(buffer);
+ }
+ catch (...)
+ {
+ CLog::Log(LOGERROR, "Error freeing preload buffer.");
+ }
+
+ return success;
+}
+
+bool CTextureBundleXPR::LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture,
+ int &width, int &height)
+{
+ DWORD ResDataOffset;
+ *ppTexture = NULL;
+
+ CAutoTexBuffer UnpackedBuf;
+ if (!LoadFile(Filename, UnpackedBuf))
+ return false;
+
+ D3DTexture *pTex = (D3DTexture *)(new char[sizeof (D3DTexture)]);
+ D3DPalette* pPal = 0;
+ void* ResData = 0;
+
+ WORD RealSize[2];
+
+ enum XPR_FLAGS
+ {
+ XPRFLAG_PALETTE = 0x00000001,
+ XPRFLAG_ANIM = 0x00000002
+ };
+
+ BYTE* Next = UnpackedBuf;
+
+ DWORD flags = Endian_SwapLE32(*(DWORD*)Next);
+ Next += sizeof(DWORD);
+ if ((flags & XPRFLAG_ANIM) || (flags >> 16) > 1)
+ goto PackedLoadError;
+
+ if (flags & XPRFLAG_PALETTE)
+ Next += sizeof(D3DPalette);
+
+ memcpy(pTex, Next, sizeof(D3DTexture));
+ pTex->Common = Endian_SwapLE32(pTex->Common);
+ pTex->Data = Endian_SwapLE32(pTex->Data);
+ pTex->Lock = Endian_SwapLE32(pTex->Lock);
+ pTex->Format = Endian_SwapLE32(pTex->Format);
+ pTex->Size = Endian_SwapLE32(pTex->Size);
+ Next += sizeof(D3DTexture);
+
+ memcpy(RealSize, Next, 4);
+ Next += 4;
+
+ ResDataOffset = ((Next - UnpackedBuf) + 127) & ~127;
+ ResData = UnpackedBuf + ResDataOffset;
+
+ if ((pTex->Common & D3DCOMMON_TYPE_MASK) != D3DCOMMON_TYPE_TEXTURE)
+ goto PackedLoadError;
+
+ GetTextureFromData(pTex, ResData, ppTexture);
+ delete[] pTex;
+
+ width = Endian_SwapLE16(RealSize[0]);
+ height = Endian_SwapLE16(RealSize[1]);
+/* DXMERGE - this was previously used to specify the format of the image - probably only affects directx?
+#ifndef HAS_SDL
+ D3DSURFACE_DESC desc;
+ (*ppTexture)->GetLevelDesc(0, &desc);
+ pInfo->Format = desc.Format;
+#endif
+*/
+ return true;
+
+PackedLoadError:
+ CLog::Log(LOGERROR, "Error loading texture: %s: Invalid data", Filename.c_str());
+ delete[] pTex;
+ delete pPal;
+ return false;
+}
+
+int CTextureBundleXPR::LoadAnim(const CStdString& Filename, CBaseTexture*** ppTextures,
+ int &width, int &height, int& nLoops, int** ppDelays)
+{
+ DWORD ResDataOffset;
+ int nTextures = 0;
+
+ *ppTextures = NULL; *ppDelays = NULL;
+
+ CAutoTexBuffer UnpackedBuf;
+ if (!LoadFile(Filename, UnpackedBuf))
+ return 0;
+
+ struct AnimInfo_t
+ {
+ DWORD nLoops;
+ WORD RealSize[2];
+ }
+ *pAnimInfo;
+
+ D3DTexture** ppTex = 0;
+ void* ResData = 0;
+
+ BYTE* Next = UnpackedBuf;
+
+ DWORD flags = Endian_SwapLE32(*(DWORD*)Next);
+ Next += sizeof(DWORD);
+ if (!(flags & XPRFLAG_ANIM))
+ goto PackedAnimError;
+
+ pAnimInfo = (AnimInfo_t*)Next;
+ Next += sizeof(AnimInfo_t);
+ nLoops = Endian_SwapLE32(pAnimInfo->nLoops);
+
+ if (flags & XPRFLAG_PALETTE)
+ Next += sizeof(D3DPalette);
+
+ nTextures = flags >> 16;
+ ppTex = new D3DTexture * [nTextures];
+ *ppDelays = new int[nTextures];
+ for (int i = 0; i < nTextures; ++i)
+ {
+ ppTex[i] = (D3DTexture *)(new char[sizeof (D3DTexture)+ sizeof (DWORD)]);
+
+ memcpy(ppTex[i], Next, sizeof(D3DTexture));
+ ppTex[i]->Common = Endian_SwapLE32(ppTex[i]->Common);
+ ppTex[i]->Data = Endian_SwapLE32(ppTex[i]->Data);
+ ppTex[i]->Lock = Endian_SwapLE32(ppTex[i]->Lock);
+ ppTex[i]->Format = Endian_SwapLE32(ppTex[i]->Format);
+ ppTex[i]->Size = Endian_SwapLE32(ppTex[i]->Size);
+ Next += sizeof(D3DTexture);
+
+ (*ppDelays)[i] = Endian_SwapLE32(*(int*)Next);
+ Next += sizeof(int);
+ }
+
+ ResDataOffset = ((DWORD)(Next - UnpackedBuf) + 127) & ~127;
+ ResData = UnpackedBuf + ResDataOffset;
+
+ *ppTextures = new CBaseTexture*[nTextures];
+ for (int i = 0; i < nTextures; ++i)
+ {
+ if ((ppTex[i]->Common & D3DCOMMON_TYPE_MASK) != D3DCOMMON_TYPE_TEXTURE)
+ goto PackedAnimError;
+
+ GetTextureFromData(ppTex[i], ResData, &(*ppTextures)[i]);
+ delete[] ppTex[i];
+ }
+
+ delete[] ppTex;
+ ppTex = 0;
+
+ width = Endian_SwapLE16(pAnimInfo->RealSize[0]);
+ height = Endian_SwapLE16(pAnimInfo->RealSize[1]);
+
+ return nTextures;
+
+PackedAnimError:
+ CLog::Log(LOGERROR, "Error loading texture: %s: Invalid data", Filename.c_str());
+ if (ppTex)
+ {
+ for (int i = 0; i < nTextures; ++i)
+ delete [] ppTex[i];
+ delete [] ppTex;
+ }
+ delete [] *ppDelays;
+ return 0;
+}
+
+void CTextureBundleXPR::SetThemeBundle(bool themeBundle)
+{
+ m_themeBundle = themeBundle;
+}
+
+// normalize to how it's stored within the bundle
+// lower case + using \\ rather than /
+CStdString CTextureBundleXPR::Normalize(const CStdString &name)
+{
+ CStdString newName(name);
+ newName.Normalize();
+ newName.Replace('/','\\');
+ return newName;
+}
diff --git a/guilib/TextureBundleXPR.h b/guilib/TextureBundleXPR.h
new file mode 100644
index 0000000000..b68ac7c3b6
--- /dev/null
+++ b/guilib/TextureBundleXPR.h
@@ -0,0 +1,69 @@
+#pragma once
+
+/*
+ * Copyright (C) 2005-2008 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "StdString.h"
+#include <stdint.h>
+#include <map>
+
+class CAutoTexBuffer;
+class CBaseTexture;
+
+class CTextureBundleXPR
+{
+ struct FileHeader_t
+ {
+ uint32_t Offset;
+ uint32_t UnpackedSize;
+ uint32_t PackedSize;
+ };
+
+ FILE* m_hFile;
+ time_t m_TimeStamp;
+
+ std::map<CStdString, FileHeader_t> m_FileHeaders;
+ typedef std::map<CStdString, FileHeader_t>::iterator iFiles;
+
+ bool m_themeBundle;
+
+ bool OpenBundle();
+ bool LoadFile(const CStdString& Filename, CAutoTexBuffer& UnpackedBuf);
+
+public:
+ CTextureBundleXPR(void);
+ ~CTextureBundleXPR(void);
+
+ void Cleanup();
+
+ void SetThemeBundle(bool themeBundle);
+ bool HasFile(const CStdString& Filename);
+ void GetTexturesFromPath(const CStdString &path, std::vector<CStdString> &textures);
+ static CStdString Normalize(const CStdString &name);
+
+ bool LoadTexture(const CStdString& Filename, CBaseTexture** ppTexture,
+ int &width, int &height);
+
+ int LoadAnim(const CStdString& Filename, CBaseTexture*** ppTextures,
+ int &width, int &height, int& nLoops, int** ppDelays);
+};
+
+
diff --git a/guilib/TextureDX.cpp b/guilib/TextureDX.cpp
index 7ed3c05816..b596b3c6a3 100644
--- a/guilib/TextureDX.cpp
+++ b/guilib/TextureDX.cpp
@@ -29,10 +29,10 @@
/************************************************************************/
/* CDXTexture */
/************************************************************************/
-CDXTexture::CDXTexture(unsigned int width, unsigned int height, unsigned int BPP)
-: CBaseTexture(width, height, BPP)
+CDXTexture::CDXTexture(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format)
+: CBaseTexture(width, height, BPP, format)
{
- Allocate(m_imageWidth, m_imageHeight, m_nBPP);
+ Allocate(m_imageWidth, m_imageHeight, m_nBPP, m_format);
}
CDXTexture::~CDXTexture()
diff --git a/guilib/TextureDX.h b/guilib/TextureDX.h
index db49a9cbd7..fc927ed582 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);
+ CDXTexture(unsigned int width = 0, unsigned int height = 0, unsigned int BPP = 0, unsigned int format = XB_FMT_UNKNOWN);
virtual ~CDXTexture();
void CreateTextureObject();
diff --git a/guilib/TextureGL.cpp b/guilib/TextureGL.cpp
index af4422a0d1..812ab626c8 100644
--- a/guilib/TextureGL.cpp
+++ b/guilib/TextureGL.cpp
@@ -31,14 +31,14 @@ using namespace std;
/************************************************************************/
/* CGLTexture */
/************************************************************************/
-CGLTexture::CGLTexture(unsigned int width, unsigned int height, unsigned int BPP)
-: CBaseTexture(width, height, BPP)
+CGLTexture::CGLTexture(unsigned int width, unsigned int height, unsigned int BPP, unsigned int format)
+: CBaseTexture(width, height, BPP, format)
{
m_nTextureWidth = 0;
m_nTextureHeight = 0;
if(m_imageWidth != 0 && m_imageHeight != 0)
- Allocate(m_imageWidth, m_imageHeight, m_nBPP);
+ Allocate(m_imageWidth, m_imageHeight, m_nBPP, m_format);
}
CGLTexture::~CGLTexture()
@@ -96,13 +96,42 @@ void CGLTexture::LoadToGPU()
m_nTextureWidth = maxSize;
}
+ GLenum format;
+
+ switch (m_format)
+ {
+ case XB_FMT_DXT1:
+ format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ break;
+ case XB_FMT_DXT3:
+ format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ break;
+ case XB_FMT_DXT5:
+ format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ break;
+ case XB_FMT_R8G8B8A8:
+ format = GL_RGBA;
+ break;
+ default:
#ifdef HAS_GL
- GLenum format = GL_BGRA;
+ format = GL_BGRA;
#elif HAS_GLES
- GLenum format = GL_BGRA_EXT;
+ format = GL_BGRA_EXT;
#endif
- glTexImage2D(GL_TEXTURE_2D, 0, 4, m_nTextureWidth, m_nTextureHeight, 0,
- format, GL_UNSIGNED_BYTE, m_pPixels);
+ 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);
+ }
+ else
+ {
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, format,
+ m_nTextureWidth, m_nTextureHeight, 0, m_bufferSize, m_pPixels);
+ }
+
#ifndef HAS_GLES
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
diff --git a/guilib/TextureGL.h b/guilib/TextureGL.h
index 962c6f462d..8631beae2a 100644
--- a/guilib/TextureGL.h
+++ b/guilib/TextureGL.h
@@ -39,7 +39,7 @@
class CGLTexture : public CBaseTexture
{
public:
- CGLTexture(unsigned int width = 0, unsigned int height = 0, unsigned int BPP = 0);
+ CGLTexture(unsigned int width = 0, unsigned int height = 0, unsigned int BPP = 0, unsigned int format = XB_FMT_B8G8R8A8);
virtual ~CGLTexture();
void CreateTextureObject();
diff --git a/guilib/TextureManager.cpp b/guilib/TextureManager.cpp
index 385404de64..c734d33a6a 100644
--- a/guilib/TextureManager.cpp
+++ b/guilib/TextureManager.cpp
@@ -232,9 +232,6 @@ const CTextureArray& CGUITextureManager::GetTexture(const CStdString& strTexture
return emptyTexture;
}
-
-
-
/************************************************************************/
/* */
/************************************************************************/
@@ -365,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, (unsigned char *)pImage->Raster, palette);
+ glTexture->LoadPaletted(pImage->Width, pImage->Height, pImage->BytesPerRow, XB_FMT_B8G8R8A8, (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
new file mode 100644
index 0000000000..e0a572d80b
--- /dev/null
+++ b/guilib/XBTF.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2005-2009 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+#include <strings.h>
+#include "XBTF.h"
+
+CXBTFFrame::CXBTFFrame()
+{
+ m_width = 0;
+ m_height = 0;
+ m_packedSize = 0;
+ m_unpackedSize = 0;
+ m_offset = 0;
+}
+
+unsigned int CXBTFFrame::GetWidth() const
+{
+ return m_width;
+}
+
+void CXBTFFrame::SetWidth(unsigned int width)
+{
+ m_width = width;
+}
+
+unsigned int CXBTFFrame::GetHeight() const
+{
+ return m_height;
+}
+
+void CXBTFFrame::SetHeight(unsigned int height)
+{
+ m_height = height;
+}
+
+unsigned long long CXBTFFrame::GetPackedSize() const
+{
+ return m_packedSize;
+}
+
+void CXBTFFrame::SetPackedSize(unsigned long long size)
+{
+ m_packedSize = size;
+}
+
+unsigned long long CXBTFFrame::GetUnpackedSize() const
+{
+ return m_unpackedSize;
+}
+
+void CXBTFFrame::SetUnpackedSize(unsigned long long size)
+{
+ m_unpackedSize = size;
+}
+
+void CXBTFFrame::SetX(unsigned int x)
+{
+ m_x = x;
+}
+
+unsigned int CXBTFFrame::GetX() const
+{
+ return m_x;
+}
+
+void CXBTFFrame::SetY(unsigned int y)
+{
+ m_y = y;
+}
+
+unsigned int CXBTFFrame::GetY() const
+{
+ return m_y;
+}
+
+unsigned long long CXBTFFrame::GetOffset() const
+{
+ return m_offset;
+}
+
+void CXBTFFrame::SetOffset(unsigned long long offset)
+{
+ m_offset = offset;
+}
+
+unsigned int CXBTFFrame::GetDuration() const
+{
+ return m_duration;
+}
+
+void CXBTFFrame::SetDuration(unsigned int duration)
+{
+ m_duration = duration;
+}
+
+
+unsigned long long CXBTFFrame::GetHeaderSize() const
+{
+ unsigned long long result =
+ sizeof(m_width) +
+ sizeof(m_height) +
+ sizeof(m_x) +
+ sizeof(m_y) +
+ sizeof(m_packedSize) +
+ sizeof(m_unpackedSize) +
+ sizeof(m_offset) +
+ sizeof(m_duration);
+
+ return result;
+}
+
+CXBTFFile::CXBTFFile()
+{
+ bzero(m_path, 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;
+}
+
+char* CXBTFFile::GetPath()
+{
+ return m_path;
+}
+
+void CXBTFFile::SetPath(const std::string& path)
+{
+ bzero(m_path, sizeof(m_path));
+ strncpy(m_path, path.c_str(), sizeof(m_path) - 1);
+}
+
+int CXBTFFile::GetLoop() const
+{
+ return m_loop;
+}
+
+void CXBTFFile::SetLoop(int loop)
+{
+ m_loop = loop;
+}
+
+unsigned int CXBTFFile::GetFormat() const
+{
+ return m_format;
+}
+
+void CXBTFFile::SetFormat(unsigned int format)
+{
+ m_format = format;
+}
+
+std::vector<CXBTFFrame>& CXBTFFile::GetFrames()
+{
+ return m_frames;
+}
+
+unsigned long long CXBTFFile::GetHeaderSize() const
+{
+ unsigned long long result =
+ sizeof(m_path) +
+ sizeof(m_loop) +
+ sizeof(m_format) +
+ sizeof(unsigned int); /* Number of frames */
+
+ for (size_t i = 0; i < m_frames.size(); i++)
+ {
+ result += m_frames[i].GetHeaderSize();
+ }
+
+ return result;
+}
+
+CXBTF::CXBTF()
+{
+}
+
+unsigned long long CXBTF::GetHeaderSize() const
+{
+ unsigned long long result =
+ 4 /* Magic */ +
+ 1 /* Vesion */ +
+ sizeof(unsigned int) /* 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;
+}
diff --git a/guilib/XBTF.h b/guilib/XBTF.h
new file mode 100644
index 0000000000..0a0d10ab2d
--- /dev/null
+++ b/guilib/XBTF.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2005-2009 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+#ifndef XBTF_H_
+#define XBTF_H_
+
+#include <string>
+#include <vector>
+
+#define XBTF_MAGIC "XBTF"
+#define XBTF_VERSION "1"
+
+#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
+
+class CXBTFFrame
+{
+public:
+ CXBTFFrame();
+ unsigned int GetWidth() const;
+ void SetWidth(unsigned int width);
+ unsigned int GetX() const;
+ void SetX(unsigned int x);
+ unsigned int GetY() const;
+ void SetY(unsigned int y);
+ unsigned int GetHeight() const;
+ void SetHeight(unsigned int height);
+ unsigned long long GetUnpackedSize() const;
+ void SetUnpackedSize(unsigned long long size);
+ unsigned long long GetPackedSize() const;
+ void SetPackedSize(unsigned long long size);
+ unsigned long long GetOffset() const;
+ void SetOffset(unsigned long long offset);
+ unsigned long long GetHeaderSize() const;
+ unsigned int GetDuration() const;
+ void SetDuration(unsigned int duration);
+
+private:
+ unsigned int m_width;
+ unsigned int m_height;
+ unsigned int m_x;
+ unsigned int m_y;
+ unsigned long long m_packedSize;
+ unsigned long long m_unpackedSize;
+ unsigned long long m_offset;
+ unsigned int m_duration;
+};
+
+class CXBTFFile
+{
+public:
+ CXBTFFile();
+ CXBTFFile(const CXBTFFile& ref);
+ char* GetPath();
+ void SetPath(const std::string& path);
+ int GetLoop() const;
+ void SetLoop(int loop);
+ unsigned int GetFormat() const;
+ void SetFormat(unsigned int format);
+
+ std::vector<CXBTFFrame>& GetFrames();
+ unsigned long long GetHeaderSize() const;
+
+private:
+ char m_path[256];
+ int m_loop;
+ unsigned int m_format;
+ std::vector<CXBTFFrame> m_frames;
+};
+
+class CXBTF
+{
+public:
+ CXBTF();
+ unsigned long long GetHeaderSize() const;
+ std::vector<CXBTFFile>& GetFiles();
+
+private:
+ std::vector<CXBTFFile> m_files;
+};
+
+#endif
diff --git a/guilib/XBTFReader.cpp b/guilib/XBTFReader.cpp
new file mode 100644
index 0000000000..9855dbae1b
--- /dev/null
+++ b/guilib/XBTFReader.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2005-2009 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <sys/stat.h>
+#include "XBTFReader.h"
+#include "EndianSwap.h"
+#include "CharsetConverter.h"
+
+#define READ_STR(str, size, file) fread(str, size, 1, file)
+#define READ_U32(i, file) fread(&i, 4, 1, file); i = Endian_SwapLE32(i);
+#define READ_U64(i, file) fread(&i, 8, 1, file); i = Endian_SwapLE64(i);
+
+CXBTFReader::CXBTFReader()
+{
+ m_file = NULL;
+}
+
+bool CXBTFReader::IsOpen() const
+{
+ return m_file != NULL;
+}
+
+bool CXBTFReader::Open(const CStdString& fileName)
+{
+ m_fileName = fileName;
+
+#ifndef _LINUX
+ CStdStringW strPathW;
+ g_charsetConverter.utf8ToW(_P(m_fileName), strPathW, false);
+ m_file = _wfopen(strPathW.c_str(), L"rb");
+#else
+ m_file = fopen(m_fileName.c_str(), "rb");
+#endif
+ if (m_file == NULL)
+ {
+ return false;
+ }
+
+ char magic[4];
+ READ_STR(magic, 4, m_file);
+
+ if (strncmp(magic, XBTF_MAGIC, sizeof(magic)) != 0)
+ {
+ return false;
+ }
+
+ char version[1];
+ READ_STR(version, 1, m_file);
+
+ if (strncmp(version, XBTF_VERSION, sizeof(version)) != 0)
+ {
+ return false;
+ }
+
+ unsigned int nofFiles;
+ READ_U32(nofFiles, m_file);
+ for (unsigned int i = 0; i < nofFiles; i++)
+ {
+ CXBTFFile file;
+ unsigned int u32;
+ unsigned long long u64;
+
+ 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;
+ READ_U32(nofFrames, m_file);
+
+ for (unsigned int j = 0; j < nofFrames; j++)
+ {
+ CXBTFFrame frame;
+
+ READ_U32(u32, m_file);
+ frame.SetWidth(u32);
+ READ_U32(u32, m_file);
+ frame.SetHeight(u32);
+ READ_U32(u32, m_file);
+ frame.SetX(u32);
+ READ_U32(u32, m_file);
+ frame.SetY(u32);
+ READ_U64(u64, m_file);
+ frame.SetPackedSize(u64);
+ READ_U64(u64, m_file);
+ frame.SetUnpackedSize(u64);
+ READ_U32(u32, m_file);
+ frame.SetDuration(u32);
+ READ_U64(u64, m_file);
+ frame.SetOffset(u64);
+
+ file.GetFrames().push_back(frame);
+ }
+
+ m_xbtf.GetFiles().push_back(file);
+
+ std::pair<CStdString, unsigned int> key = std::make_pair(file.GetPath(), file.GetFormat());
+ m_filesMap[key] = file;
+ }
+
+ // Sanity check
+ fpos_t pos;
+ fgetpos(m_file, &pos);
+ if ((unsigned int) pos != m_xbtf.GetHeaderSize())
+ {
+ printf("Expected header size (%llu) != actual size (%llu)\n", m_xbtf.GetHeaderSize(), pos);
+ return false;
+ }
+
+ return true;
+}
+
+void CXBTFReader::Close()
+{
+ if (m_file)
+ {
+ fclose(m_file);
+ m_file = NULL;
+ }
+
+ m_xbtf.GetFiles().clear();
+ m_filesMap.clear();
+}
+
+time_t CXBTFReader::GetLastModificationTimestamp()
+{
+ if (!m_file)
+ {
+ return 0;
+ }
+
+ struct stat fileStat;
+ if (fstat(fileno(m_file), &fileStat) == -1)
+ {
+ return 0;
+ }
+
+ return fileStat.st_mtime;
+}
+
+bool CXBTFReader::Exists(const CStdString& name, int formatMask)
+{
+ return Find(name, formatMask) != NULL;
+}
+
+CXBTFFile* CXBTFReader::Find(const CStdString& name, int formatMask)
+{
+ 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);
+ if (iter == m_filesMap.end())
+ {
+ return NULL;
+ }
+
+ return &(iter->second);
+}
+
+bool CXBTFReader::Load(const CXBTFFrame& frame, unsigned char* buffer)
+{
+ if (!m_file)
+ {
+ return false;
+ }
+
+ if (fseek(m_file, frame.GetOffset(), SEEK_SET) == -1)
+ {
+ return false;
+ }
+
+ if (fread(buffer, 1, frame.GetPackedSize(), m_file) != frame.GetPackedSize())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+std::vector<CXBTFFile>& CXBTFReader::GetFiles()
+{
+ return m_xbtf.GetFiles();
+}
diff --git a/guilib/XBTFReader.h b/guilib/XBTFReader.h
new file mode 100644
index 0000000000..a24d44084d
--- /dev/null
+++ b/guilib/XBTFReader.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2005-2009 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#ifndef XBTFREADER_H_
+#define XBTFREADER_H_
+
+#include <vector>
+#include <map>
+#include "StdString.h"
+#include "XBTF.h"
+
+class CXBTFReader
+{
+public:
+ CXBTFReader();
+ bool IsOpen() const;
+ 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 Load(const CXBTFFrame& frame, unsigned char* buffer);
+ std::vector<CXBTFFile>& GetFiles();
+
+private:
+ CXBTF m_xbtf;
+ CStdString m_fileName;
+ FILE* m_file;
+ std::map<std::pair<CStdString, unsigned int>, CXBTFFile> m_filesMap;
+};
+
+#endif
diff --git a/skin/PM3.HD/media/Makefile b/skin/PM3.HD/media/Makefile
index 4ea9204b5f..3074a96711 100644
--- a/skin/PM3.HD/media/Makefile
+++ b/skin/PM3.HD/media/Makefile
@@ -1,5 +1,5 @@
-TARGET=Textures.xpr
-XBMCTEX=../../../tools/XBMCTex/XBMCTex
+TARGET=Textures.xbt
+XBMCTEX=../../../tools/XBMCTexXBT/XBMCTexXBT
IMAGES= \
Apple\ Movie\ Trailers/G.png \
Apple\ Movie\ Trailers/NC-17.png \
@@ -325,7 +325,7 @@ $(TARGET): $(XBMCTEX) $(IMAGES)
$(XBMCTEX) -input . -output $(TARGET)
$(XBMCTEX): force
- $(MAKE) -C ../../../tools/XBMCTex
+ $(MAKE) -C ../../../tools/XBMCTexXBT
clean:
rm -f $(TARGET)
diff --git a/skin/Project Mayhem III/media/Makefile b/skin/Project Mayhem III/media/Makefile
index 473c7c08db..e24063e066 100644
--- a/skin/Project Mayhem III/media/Makefile
+++ b/skin/Project Mayhem III/media/Makefile
@@ -1,5 +1,5 @@
-TARGET=Textures.xpr
-XBMCTEX=../../../tools/XBMCTex/XBMCTex
+TARGET=Textures.xbt
+XBMCTEX=../../../tools/XBMCTexXBT/XBMCTexXBT
IMAGES= \
busy/busy1.png \
busy/busy2.png \
@@ -378,7 +378,7 @@ $(TARGET): $(XBMCTEX) $(IMAGES)
$(XBMCTEX) -input . -output $(TARGET)
$(XBMCTEX): force
- $(MAKE) -C ../../../tools/XBMCTex
+ $(MAKE) -C ../../../tools/XBMCTexXBT
clean:
rm -f $(TARGET)
diff --git a/tools/XBMCTexXBT/Makefile b/tools/XBMCTexXBT/Makefile
new file mode 100644
index 0000000000..845e6cbf66
--- /dev/null
+++ b/tools/XBMCTexXBT/Makefile
@@ -0,0 +1,17 @@
+INCLUDES =-I../../xbmc/utils -I../../guilib -I../../xbmc/linux -I../../xbmc/lib/libsquish
+DEFINES =
+LIBS = ../../xbmc/lib/libsquish/libsquish.a ../../guilib/XBTF.o -L/opt/local/lib -lSDL_image -lSDL
+OBJS = \
+ SDL_anigif.o \
+ XBTFWriter.o \
+ XBMCTex.o \
+
+TARGET = XBMCTexXBT
+CLEAN_FILES=$(TARGET)
+
+all: $(TARGET)
+
+include ../../Makefile.include
+
+$(TARGET): $(OBJS)
+ $(CXX) $(OBJS) $(LDFLAGS) $(LIBS) -o $(TARGET)
diff --git a/tools/XBMCTexXBT/SDL_anigif.c b/tools/XBMCTexXBT/SDL_anigif.c
new file mode 100644
index 0000000000..b77b7bcdb0
--- /dev/null
+++ b/tools/XBMCTexXBT/SDL_anigif.c
@@ -0,0 +1,776 @@
+/*
+ SDL_anigif: An example animated GIF image loading library for use with SDL
+ SDL_image Copyright (C) 1997-2006 Sam Lantinga
+ Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "SDL_anigif.h"
+
+
+
+/* Code from here to end of file has been adapted from XPaint: */
+/* +-------------------------------------------------------------------+ */
+/* | Copyright 1990, 1991, 1993 David Koblas. | */
+/* | Copyright 1996 Torsten Martinsen. | */
+/* | Permission to use, copy, modify, and distribute this software | */
+/* | and its documentation for any purpose and without fee is hereby | */
+/* | granted, provided that the above copyright notice appear in all | */
+/* | copies and that both that copyright notice and this permission | */
+/* | notice appear in supporting documentation. This software is | */
+/* | provided "as is" without express or implied warranty. | */
+/* +-------------------------------------------------------------------+ */
+/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */
+/* Animated GIF support by Doug McFadyen -- 10/19/06 */
+
+#define MAXCOLORMAPSIZE 256
+
+#define TRUE 1
+#define FALSE 0
+
+#define CM_RED 0
+#define CM_GREEN 1
+#define CM_BLUE 2
+
+#define MAX_LWZ_BITS 12
+
+#define INTERLACE 0x40
+#define LOCALCOLORMAP 0x80
+#define BitSet(byte,bit) (((byte) & (bit)) == (bit))
+#define LM_to_uint(a,b) (((b)<<8)|(a))
+
+#define SDL_SetError(t) ((void)0) /* We're not SDL so ignore error reporting */
+
+
+typedef struct
+{
+ unsigned int Width;
+ unsigned int Height;
+ unsigned char ColorMap[3][MAXCOLORMAPSIZE];
+ unsigned int BitPixel;
+ unsigned int ColorResolution;
+ unsigned int Background;
+ unsigned int AspectRatio;
+} gifscreen;
+
+typedef struct
+{
+ int transparent;
+ int delayTime;
+ int inputFlag;
+ int disposal;
+} gif89;
+
+typedef struct
+{
+ /* global data */
+ SDL_RWops* src;
+ gifscreen gs;
+ gif89 g89;
+ int zerodatablock;
+ /* AG_LoadGIF_RW data */
+ unsigned char localColorMap[3][MAXCOLORMAPSIZE];
+ /* GetCode data */
+ unsigned char buf[280];
+ int curbit, lastbit, done, lastbyte;
+ /* LWZReadByte data */
+ int fresh, code, incode;
+ int codesize, setcodesize;
+ int maxcode, maxcodesize;
+ int firstcode, oldcode;
+ int clearcode, endcode;
+ int table[2][(1 << MAX_LWZ_BITS)];
+ int stack[(1 << (MAX_LWZ_BITS))*2], *sp;
+} gifdata;
+
+
+
+static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] );
+static int DoExtension( gifdata* gd, int label );
+static int GetDataBlock( gifdata* gd, unsigned char* buf );
+static int GetCode( gifdata* gd, int code_size, int flag );
+static int LWZReadByte( gifdata* gd, int flag, int input_code_size );
+static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore );
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_isGIF( SDL_RWops* src )
+{
+ int isGIF = FALSE;
+
+ if ( src )
+ {
+ int start = SDL_RWtell( src );
+ char magic[6];
+
+ if ( SDL_RWread(src,magic,sizeof(magic),1) )
+ {
+ if ( (strncmp(magic,"GIF",3) == 0) && ((memcmp(magic+3,"87a",3) == 0) || (memcmp(magic+3,"89a",3) == 0)) )
+ {
+ isGIF = TRUE;
+ }
+ }
+
+ SDL_RWseek( src, start, SEEK_SET );
+ }
+
+ return isGIF;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_LoadGIF( const char* file, AG_Frame* frames, int size )
+{
+ int n = 0;
+
+ SDL_RWops* src = SDL_RWFromFile( file, "rb" );
+
+ if ( src )
+ {
+ n = AG_LoadGIF_RW( src, frames, size );
+ SDL_RWclose( src );
+ }
+
+ return n;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+void AG_FreeSurfaces( AG_Frame* frames, int nFrames )
+{
+ int i;
+
+ if ( frames )
+ {
+ for ( i = 0; i < nFrames; i++ )
+ {
+ if ( frames[i].surface )
+ {
+ SDL_FreeSurface( frames[i].surface );
+ frames[i].surface = NULL;
+ }
+ }
+ }
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames )
+{
+ int i;
+ int n = 0;
+
+ if ( frames )
+ {
+ for ( i = 0; i < nFrames; i++ )
+ {
+ if ( frames[i].surface )
+ {
+ SDL_Surface* surface = (frames[i].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[i].surface) : SDL_DisplayFormat(frames[i].surface);
+
+ if ( surface )
+ {
+ SDL_FreeSurface( frames[i].surface );
+ frames[i].surface = surface;
+ n++;
+ }
+ }
+ }
+ }
+
+ return n;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames )
+{
+ int n = 0;
+
+ if ( nFrames > 0 && frames && frames[0].surface )
+ {
+ SDL_Surface* mainSurface = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[0].surface) : SDL_DisplayFormat(frames[0].surface);
+ const int newDispose = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? AG_DISPOSE_RESTORE_BACKGROUND : AG_DISPOSE_NONE;
+
+ if ( mainSurface )
+ {
+ int i;
+ int lastDispose = AG_DISPOSE_NA;
+ int iRestore = 0;
+ const Uint8 alpha = (frames[0].disposal == AG_DISPOSE_NONE) ? SDL_ALPHA_OPAQUE : SDL_ALPHA_TRANSPARENT;
+
+ SDL_FillRect( mainSurface, NULL, SDL_MapRGBA(mainSurface->format,0,0,0,alpha) );
+
+ for ( i = 0; i < nFrames; i++ )
+ {
+ if ( frames[i].surface )
+ {
+ SDL_Surface* surface = SDL_ConvertSurface( mainSurface, mainSurface->format, mainSurface->flags );
+
+ if ( surface )
+ {
+ SDL_Rect r;
+
+ if ( lastDispose == AG_DISPOSE_NONE )
+ SDL_BlitSurface( frames[i-1].surface, NULL, surface, NULL );
+
+ if ( lastDispose == AG_DISPOSE_RESTORE_PREVIOUS )
+ SDL_BlitSurface( frames[iRestore].surface, NULL, surface, NULL );
+ if ( frames[i].disposal != AG_DISPOSE_RESTORE_PREVIOUS )
+ iRestore = i;
+
+ r.x = (Sint16)frames[i].x;
+ r.y = (Sint16)frames[i].y;
+ SDL_BlitSurface( frames[i].surface, NULL, surface, &r );
+
+ SDL_FreeSurface( frames[i].surface );
+ frames[i].surface = surface;
+ frames[i].x = frames[i].y = 0;
+ lastDispose = frames[i].disposal;
+ frames[i].disposal = newDispose;
+ n++;
+ }
+ }
+ }
+
+ SDL_FreeSurface( mainSurface );
+ }
+ }
+
+ return n;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int maxFrames )
+{
+ int start;
+ unsigned char buf[16];
+ unsigned char c;
+ int useGlobalColormap;
+ int bitPixel;
+ int iFrame = 0;
+ char version[4];
+ SDL_Surface* image = NULL;
+ gifdata* gd;
+
+ if ( src == NULL )
+ return 0;
+
+ gd = malloc( sizeof(*gd) );
+ memset( gd, 0, sizeof(*gd) );
+ gd->src = src;
+
+ start = SDL_RWtell( src );
+
+ if ( !SDL_RWread(src,buf,6,1) )
+ {
+ SDL_SetError( "error reading magic number" );
+ goto done;
+ }
+
+ if ( strncmp((char*)buf,"GIF",3) != 0 )
+ {
+ SDL_SetError( "not a GIF file" );
+ goto done;
+ }
+
+ strncpy( version, (char*)buf+3, 3 );
+ version[3] = '\0';
+
+ if ( (strcmp(version,"87a") != 0) && (strcmp(version,"89a") != 0) )
+ {
+ SDL_SetError( "bad version number, not '87a' or '89a'" );
+ goto done;
+ }
+
+ gd->g89.transparent = -1;
+ gd->g89.delayTime = -1;
+ gd->g89.inputFlag = -1;
+ gd->g89.disposal = AG_DISPOSE_NA;
+
+ if ( !SDL_RWread(src,buf,7,1) )
+ {
+ SDL_SetError( "failed to read screen descriptor" );
+ goto done;
+ }
+
+ gd->gs.Width = LM_to_uint(buf[0],buf[1]);
+ gd->gs.Height = LM_to_uint(buf[2],buf[3]);
+ gd->gs.BitPixel = 2 << (buf[4] & 0x07);
+ gd->gs.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
+ gd->gs.Background = buf[5];
+ gd->gs.AspectRatio = buf[6];
+
+ if ( BitSet(buf[4],LOCALCOLORMAP) ) /* Global Colormap */
+ {
+ if ( ReadColorMap(gd,gd->gs.BitPixel,gd->gs.ColorMap) )
+ {
+ SDL_SetError( "error reading global colormap" );
+ goto done;
+ }
+ }
+
+ do
+ {
+ if ( !SDL_RWread(src,&c,1,1) )
+ {
+ SDL_SetError( "EOF / read error on image data" );
+ goto done;
+ }
+
+ if ( c == ';' ) /* GIF terminator */
+ goto done;
+
+ if ( c == '!' ) /* Extension */
+ {
+ if ( !SDL_RWread(src,&c,1,1) )
+ {
+ SDL_SetError( "EOF / read error on extention function code" );
+ goto done;
+ }
+ DoExtension( gd, c );
+ continue;
+ }
+
+ if ( c != ',' ) /* Not a valid start character */
+ continue;
+
+ if ( !SDL_RWread(src,buf,9,1) )
+ {
+ SDL_SetError( "couldn't read left/top/width/height" );
+ goto done;
+ }
+
+ useGlobalColormap = !BitSet(buf[8],LOCALCOLORMAP);
+ bitPixel = 1 << ((buf[8] & 0x07) + 1);
+
+ if ( !useGlobalColormap )
+ {
+ if ( ReadColorMap(gd,bitPixel,gd->localColorMap) )
+ {
+ SDL_SetError( "error reading local colormap" );
+ goto done;
+ }
+ image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), bitPixel, gd->localColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) );
+ }
+ else
+ {
+ image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), gd->gs.BitPixel, gd->gs.ColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) );
+ }
+
+ if ( frames )
+ {
+ if ( image == NULL )
+ goto done;
+
+ if ( gd->g89.transparent >= 0 )
+ SDL_SetColorKey( image, SDL_SRCCOLORKEY, gd->g89.transparent );
+
+ frames[iFrame].surface = image;
+ frames[iFrame].x = LM_to_uint(buf[0], buf[1]);
+ frames[iFrame].y = LM_to_uint(buf[2], buf[3]);
+ frames[iFrame].disposal = gd->g89.disposal;
+ frames[iFrame].delay = gd->g89.delayTime*10;
+/* gd->g89.transparent = -1; ** Hmmm, not sure if this should be reset for each frame? */
+ }
+
+ iFrame++;
+ } while ( iFrame < maxFrames || frames == NULL );
+
+done:
+ if ( image == NULL )
+ SDL_RWseek( src, start, SEEK_SET );
+
+ free( gd );
+
+ return iFrame;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] )
+{
+ int i;
+ unsigned char rgb[3];
+ int flag;
+
+ flag = TRUE;
+
+ for ( i = 0; i < number; ++i )
+ {
+ if ( !SDL_RWread(gd->src,rgb,sizeof(rgb),1) )
+ {
+ SDL_SetError( "bad colormap" );
+ return 1;
+ }
+
+ buffer[CM_RED][i] = rgb[0];
+ buffer[CM_GREEN][i] = rgb[1];
+ buffer[CM_BLUE][i] = rgb[2];
+ flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
+ }
+
+ return FALSE;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int DoExtension( gifdata* gd, int label )
+{
+ unsigned char buf[256];
+
+ switch ( label )
+ {
+ case 0x01: /* Plain Text Extension */
+ break;
+
+ case 0xff: /* Application Extension */
+ break;
+
+ case 0xfe: /* Comment Extension */
+ while ( GetDataBlock(gd,buf) != 0 )
+ ;
+ return FALSE;
+
+ case 0xf9: /* Graphic Control Extension */
+ (void)GetDataBlock( gd, buf );
+ gd->g89.disposal = (buf[0] >> 2) & 0x7;
+ gd->g89.inputFlag = (buf[0] >> 1) & 0x1;
+ gd->g89.delayTime = LM_to_uint(buf[1],buf[2]);
+ if ( (buf[0] & 0x1) != 0 )
+ gd->g89.transparent = buf[3];
+
+ while ( GetDataBlock(gd,buf) != 0 )
+ ;
+ return FALSE;
+ }
+
+ while ( GetDataBlock(gd,buf) != 0 )
+ ;
+
+ return FALSE;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int GetDataBlock( gifdata* gd, unsigned char* buf )
+{
+ unsigned char count;
+
+ if ( !SDL_RWread(gd->src,&count,1,1) )
+ {
+ /* pm_message("error in getting DataBlock size" ); */
+ return -1;
+ }
+
+ gd->zerodatablock = count == 0;
+
+ if ( (count != 0) && !SDL_RWread(gd->src,buf,count,1) )
+ {
+ /* pm_message("error in reading DataBlock" ); */
+ return -1;
+ }
+
+ return count;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int GetCode( gifdata* gd, int code_size, int flag )
+{
+ int i, j, ret;
+ int count;
+
+ if ( flag )
+ {
+ gd->curbit = 0;
+ gd->lastbit = 0;
+ gd->done = FALSE;
+ return 0;
+ }
+
+ if ( (gd->curbit + code_size) >= gd->lastbit )
+ {
+ if ( gd->done )
+ {
+ if ( gd->curbit >= gd->lastbit )
+ SDL_SetError( "ran off the end of my bits" );
+ return -1;
+ }
+
+ gd->buf[0] = gd->buf[gd->lastbyte - 2];
+ gd->buf[1] = gd->buf[gd->lastbyte - 1];
+
+ if ( (count = GetDataBlock(gd, &gd->buf[2])) == 0 )
+ gd->done = TRUE;
+
+ gd->lastbyte = 2 + count;
+ gd->curbit = (gd->curbit - gd->lastbit) + 16;
+ gd->lastbit = (2 + count)*8;
+ }
+
+ ret = 0;
+ for ( i = gd->curbit, j = 0; j < code_size; ++i, ++j )
+ ret |= ((gd->buf[i / 8] & (1 << (i % 8))) != 0) << j;
+
+ gd->curbit += code_size;
+
+ return ret;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int LWZReadByte( gifdata* gd, int flag, int input_code_size )
+{
+ int i, code, incode;
+
+ if ( flag )
+ {
+ gd->setcodesize = input_code_size;
+ gd->codesize = gd->setcodesize + 1;
+ gd->clearcode = 1 << gd->setcodesize;
+ gd->endcode = gd->clearcode + 1;
+ gd->maxcodesize = gd->clearcode*2;
+ gd->maxcode = gd->clearcode + 2;
+
+ GetCode( gd, 0, TRUE );
+
+ gd->fresh = TRUE;
+
+ for ( i = 0; i < gd->clearcode; ++i )
+ {
+ gd->table[0][i] = 0;
+ gd->table[1][i] = i;
+ }
+
+ for ( ; i < (1 << MAX_LWZ_BITS); ++i )
+ gd->table[0][i] = gd->table[1][0] = 0;
+
+ gd->sp = gd->stack;
+ return 0;
+ }
+ else if ( gd->fresh )
+ {
+ gd->fresh = FALSE;
+ do
+ {
+ gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE );
+ } while ( gd->firstcode == gd->clearcode );
+ return gd->firstcode;
+ }
+
+ if ( gd->sp > gd->stack )
+ return *--gd->sp;
+
+ while ( (code = GetCode(gd,gd->codesize,FALSE)) >= 0 )
+ {
+ if ( code == gd->clearcode )
+ {
+ for ( i = 0; i < gd->clearcode; ++i )
+ {
+ gd->table[0][i] = 0;
+ gd->table[1][i] = i;
+ }
+
+ for ( ; i < (1 << MAX_LWZ_BITS); ++i )
+ gd->table[0][i] = gd->table[1][i] = 0;
+
+ gd->codesize = gd->setcodesize + 1;
+ gd->maxcodesize = gd->clearcode*2;
+ gd->maxcode = gd->clearcode + 2;
+ gd->sp = gd->stack;
+ gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE );
+ return gd->firstcode;
+ }
+ else if ( code == gd->endcode )
+ {
+ int count;
+ unsigned char buf[260];
+
+ if ( gd->zerodatablock )
+ return -2;
+
+ while ( (count = GetDataBlock(gd,buf)) > 0 )
+ ;
+
+ if ( count != 0 )
+ {
+ /* pm_message("missing EOD in data stream (common occurence)"); */
+ }
+ return -2;
+ }
+
+ incode = code;
+
+ if ( code >= gd->maxcode )
+ {
+ *gd->sp++ = gd->firstcode;
+ code = gd->oldcode;
+ }
+
+ while ( code >= gd->clearcode )
+ {
+ *gd->sp++ = gd->table[1][code];
+ if ( code == gd->table[0][code] )
+ SDL_SetError( "circular table entry BIG ERROR" );
+ code = gd->table[0][code];
+ }
+
+ *gd->sp++ = gd->firstcode = gd->table[1][code];
+
+ if ( (code = gd->maxcode) < (1 << MAX_LWZ_BITS) )
+ {
+ gd->table[0][code] = gd->oldcode;
+ gd->table[1][code] = gd->firstcode;
+ ++gd->maxcode;
+ if ( (gd->maxcode >= gd->maxcodesize) && (gd->maxcodesize < (1 << MAX_LWZ_BITS)) )
+ {
+ gd->maxcodesize *= 2;
+ ++gd->codesize;
+ }
+ }
+
+ gd->oldcode = incode;
+
+ if ( gd->sp > gd->stack )
+ return *--gd->sp;
+ }
+
+ return code;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int cmapSize, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore )
+{
+ SDL_Surface* image;
+ unsigned char c;
+ int i, v;
+ int xpos = 0, ypos = 0, pass = 0;
+
+ /* Initialize the compression routines */
+ if ( !SDL_RWread(gd->src,&c,1,1) )
+ {
+ SDL_SetError( "EOF / read error on image data" );
+ return NULL;
+ }
+
+ if ( LWZReadByte(gd,TRUE,c) < 0 )
+ {
+ SDL_SetError( "error reading image" );
+ return NULL;
+ }
+
+ /* If this is an "uninteresting picture" ignore it. */
+ if ( ignore )
+ {
+ while ( LWZReadByte(gd,FALSE,c) >= 0 )
+ ;
+ return NULL;
+ }
+
+ image = SDL_AllocSurface( SDL_SWSURFACE, len, height, 8, 0, 0, 0, 0 );
+
+ for ( i = 0; i < cmapSize; i++ )
+ {
+ image->format->palette->colors[i].r = cmap[CM_RED][i];
+ image->format->palette->colors[i].g = cmap[CM_GREEN][i];
+ image->format->palette->colors[i].b = cmap[CM_BLUE][i];
+ }
+
+ while ( (v = LWZReadByte(gd,FALSE,c)) >= 0 )
+ {
+ ((Uint8*)image->pixels)[xpos + ypos*image->pitch] = (Uint8)v;
+ ++xpos;
+
+ if ( xpos == len )
+ {
+ xpos = 0;
+ if ( interlace )
+ {
+ switch ( pass )
+ {
+ case 0:
+ case 1: ypos += 8; break;
+ case 2: ypos += 4; break;
+ case 3: ypos += 2; break;
+ }
+
+ if ( ypos >= height )
+ {
+ ++pass;
+ switch ( pass )
+ {
+ case 1: ypos = 4; break;
+ case 2: ypos = 2; break;
+ case 3: ypos = 1; break;
+ default: goto fini;
+ }
+ }
+ }
+ else
+ {
+ ++ypos;
+ }
+ }
+
+ if ( ypos >= height )
+ break;
+ }
+
+fini:
+ return image;
+}
+
diff --git a/tools/XBMCTexXBT/SDL_anigif.h b/tools/XBMCTexXBT/SDL_anigif.h
new file mode 100644
index 0000000000..7fad7c8fdb
--- /dev/null
+++ b/tools/XBMCTexXBT/SDL_anigif.h
@@ -0,0 +1,62 @@
+/*
+ SDL_anigif: An example animated GIF image loading library for use with SDL
+ SDL_image Copyright (C) 1997-2006 Sam Lantinga
+ Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _SDL_ANIGIF_H
+#define _SDL_ANIGIF_H
+
+#include <SDL/SDL.h>
+#include <SDL/begin_code.h>
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+typedef struct
+{
+ SDL_Surface* surface; /* SDL surface for this frame */
+ int x, y; /* Frame offset position */
+ int disposal; /* Disposal code */
+ int delay; /* Frame delay in ms */
+ int user; /* User data (not used by aniGIF) */
+} AG_Frame;
+
+#define AG_DISPOSE_NA 0 /* No disposal specified */
+#define AG_DISPOSE_NONE 1 /* Do not dispose */
+#define AG_DISPOSE_RESTORE_BACKGROUND 2 /* Restore to background */
+#define AG_DISPOSE_RESTORE_PREVIOUS 3 /* Restore to previous */
+
+
+
+extern DECLSPEC int AG_isGIF( SDL_RWops* src );
+extern DECLSPEC int AG_LoadGIF( const char* file, AG_Frame* frames, int maxFrames );
+extern DECLSPEC void AG_FreeSurfaces( AG_Frame* frames, int nFrames );
+extern DECLSPEC int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames );
+extern DECLSPEC int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames );
+extern DECLSPEC int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int size );
+
+
+
+#ifdef __cplusplus
+ }
+#endif
+#include <SDL/close_code.h>
+
+#endif /* _SDL_ANIGIF_H */
diff --git a/tools/XBMCTexXBT/XBMCTex.cpp b/tools/XBMCTexXBT/XBMCTex.cpp
new file mode 100644
index 0000000000..abe5deb89e
--- /dev/null
+++ b/tools/XBMCTexXBT/XBMCTex.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2005-2009 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <squish.h>
+#include <string>
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include "XBTF.h"
+#include "XBTFWriter.h"
+#include "SDL_anigif.h"
+#include "cmdlineargs.h"
+
+#define DIR_SEPARATOR "/"
+#define DIR_SEPARATOR_CHAR '/'
+
+#undef main
+
+// 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))
+ return false;
+
+ return true;
+}
+
+// returns true for png, bmp, tga, jpg and dds files, otherwise returns false
+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;
+}
+
+void CreateSkeletonHeaderImpl(CXBTF& xbtf, std::string fullPath, std::string relativePath)
+{
+ 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;
+ if (tmpPath.size() > 0)
+ {
+ tmpPath += "/";
+ }
+
+ CreateSkeletonHeaderImpl(xbtf, fullPath + DIR_SEPARATOR + dp->d_name,
+ tmpPath + dp->d_name);
+ }
+ else if (IsGraphicsFile(dp->d_name))
+ {
+ std::string fileName = "";
+ if (relativePath.size() > 0)
+ {
+ 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);
+}
+
+CXBTFFrame createXBTFFrame(SDL_Surface* image, CXBTFWriter& writer, unsigned int format)
+{
+ // Convert to RGBA
+ SDL_PixelFormat rgbaFormat;
+ bzero(&rgbaFormat, sizeof(SDL_PixelFormat));
+ rgbaFormat.BitsPerPixel = 32;
+ rgbaFormat.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;
+#endif
+
+
+ SDL_Surface *rgbaImage = SDL_ConvertSurface(image, &rgbaFormat, 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);
+
+ return frame;
+}
+
+void Usage()
+{
+ puts("Usage:");
+ puts(" -help Show this screen.");
+ puts(" -input <dir> Input directory. Default: current dir");
+ puts(" -output <dir> Output directory/filename. Default: Textures.xpr");
+}
+
+int createBundle(const std::string& InputDir, const std::string& OutputFile)
+{
+ 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();
+
+ if (!IsGIF(fullPath.c_str()))
+ {
+ // Load the image
+ SDL_Surface* image = IMG_Load(fullPath.c_str());
+ if (!image)
+ {
+ printf("...unable to load image\n");
+ 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);
+ }
+ else
+ {
+ 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);
+
+ 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);
+ frame.SetDuration(gpAG[j].delay);
+ file.GetFrames().push_back(frame);
+ }
+
+ AG_FreeSurfaces(gpAG, gnAG);
+ delete [] gpAG;
+
+ file.SetLoop(0);
+ }
+ }
+
+ if (!writer.UpdateHeader())
+ {
+ printf("Error writing header to file\n");
+ return 1;
+ }
+
+ if (!writer.Close())
+ {
+ printf("Error closing file\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ bool valid = false;
+ CmdLineArgs args(argc, (const char**)argv);
+
+ if (args.size() == 1)
+ {
+ Usage();
+ return 1;
+ }
+
+ std::string InputDir;
+ std::string OutputFilename = "Textures.xbt";
+
+ for (unsigned int i = 1; i < args.size(); ++i)
+ {
+ if (!stricmp(args[i], "-help") || !stricmp(args[i], "-h") || !stricmp(args[i], "-?"))
+ {
+ Usage();
+ return 1;
+ }
+ else if (!stricmp(args[i], "-input") || !stricmp(args[i], "-i"))
+ {
+ InputDir = args[++i];
+ valid = true;
+ }
+ else if (!stricmp(args[i], "-output") || !stricmp(args[i], "-o"))
+ {
+ OutputFilename = args[++i];
+ valid = true;
+#ifdef _LINUX
+ char *c = NULL;
+ while ((c = (char *)strchr(OutputFilename.c_str(), '\\')) != NULL) *c = '/';
+#endif
+ }
+ else
+ {
+ printf("Unrecognized command line flag: %s\n", args[i]);
+ }
+ }
+
+ if (!valid)
+ {
+ Usage();
+ return 1;
+ }
+
+ size_t pos = InputDir.find_last_of(DIR_SEPARATOR);
+ if (pos != InputDir.length()-1)
+ {
+ InputDir += DIR_SEPARATOR;
+ }
+
+ createBundle(InputDir, OutputFilename);
+}
diff --git a/tools/XBMCTexXBT/XBTFWriter.cpp b/tools/XBMCTexXBT/XBTFWriter.cpp
new file mode 100644
index 0000000000..c196a0837a
--- /dev/null
+++ b/tools/XBMCTexXBT/XBTFWriter.cpp
@@ -0,0 +1,133 @@
+#include "XBTFWriter.h"
+#include "EndianSwap.h"
+
+#define TEMP_FILE "temp.xbt"
+#define TEMP_SIZE (10*1024*1024)
+
+#define WRITE_STR(str, size, file) fwrite(str, size, 1, file)
+#define WRITE_U32(i, file) { unsigned long _n = i; _n = Endian_SwapLE32(i); fwrite(&_n, 4, 1, file); }
+#define WRITE_U64(i, file) { unsigned long long _n = i; _n = Endian_SwapLE64(i); fwrite(&_n, 8, 1, file); }
+
+CXBTFWriter::CXBTFWriter(CXBTF& xbtf, const std::string outputFile) : m_xbtf(xbtf)
+{
+ m_outputFile = outputFile;
+ m_file = NULL;
+}
+
+bool CXBTFWriter::Create()
+{
+ m_file = fopen(m_outputFile.c_str(), "wb");
+ if (m_file == NULL)
+ {
+ return false;
+ }
+
+ m_tempFile = fopen(TEMP_FILE, "wb");
+ if (m_tempFile == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool CXBTFWriter::Close()
+{
+ if (m_file == NULL || m_tempFile == NULL)
+ {
+ return false;
+ }
+
+ fclose(m_tempFile);
+ m_tempFile = fopen(TEMP_FILE, "rb");
+ if (m_tempFile == NULL)
+ {
+ 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)
+{
+ if (m_tempFile == NULL)
+ {
+ return false;
+ }
+
+ fwrite(data, length, 1, m_tempFile);
+
+ return true;
+}
+
+bool CXBTFWriter::UpdateHeader()
+{
+ if (m_file == NULL)
+ {
+ return false;
+ }
+
+ unsigned long long 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)
+ {
+ *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++)
+ {
+ 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_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
+ fpos_t pos;
+ fgetpos(m_file, &pos);
+ if ((unsigned int) pos != m_xbtf.GetHeaderSize())
+ {
+ printf("Expected header size (%llu) != actual size (%llu)\n", m_xbtf.GetHeaderSize(), pos);
+ return false;
+ }
+
+ return true;
+}
diff --git a/tools/XBMCTexXBT/XBTFWriter.h b/tools/XBMCTexXBT/XBTFWriter.h
new file mode 100644
index 0000000000..810f3ddce3
--- /dev/null
+++ b/tools/XBMCTexXBT/XBTFWriter.h
@@ -0,0 +1,24 @@
+#ifndef XBTFWRITER_H_
+#define XBTFWRITER_H_
+
+#include <string>
+#include <stdio.h>
+#include "XBTF.h"
+
+class CXBTFWriter
+{
+public:
+ CXBTFWriter(CXBTF& xbtf, const std::string outputFile);
+ bool Create();
+ bool Close();
+ bool AppendContent(unsigned char* data, size_t length);
+ bool UpdateHeader();
+
+private:
+ CXBTF& m_xbtf;
+ std::string m_outputFile;
+ FILE* m_file;
+ FILE* m_tempFile;
+};
+
+#endif
diff --git a/tools/XBMCTexXBT/cmdlineargs.h b/tools/XBMCTexXBT/cmdlineargs.h
new file mode 100644
index 0000000000..a9f5891722
--- /dev/null
+++ b/tools/XBMCTexXBT/cmdlineargs.h
@@ -0,0 +1,123 @@
+#ifndef CMDLINEARGS_H
+#define CMDLINEARGS_H
+
+#ifdef _LINUX
+#include "PlatformDefs.h"
+#include "xwinapi.h"
+typedef LPSTR PSZ;
+#define _snprintf snprintf
+#else
+#include <windows.h>
+#endif
+#include <vector>
+#include <string>
+
+class CmdLineArgs : public std::vector<char*>
+{
+public:
+ CmdLineArgs ()
+ {
+ // Save local copy of the command line string, because
+ // ParseCmdLine() modifies this string while parsing it.
+ PSZ cmdline = GetCommandLine();
+ m_cmdline = new char [strlen (cmdline) + 1];
+ if (m_cmdline)
+ {
+ strcpy (m_cmdline, cmdline);
+ ParseCmdLine();
+ } else {
+#ifdef _LINUX
+ delete[] cmdline;
+#endif
+ }
+ }
+
+ CmdLineArgs (const int argc, const char **argv)
+ {
+ std::string cmdline;
+ for (int i = 0 ; i<argc ; i++)
+ {
+ cmdline += std::string(argv[i]);
+ if ( i != (argc-1) )
+ {
+ cmdline += " ";
+ }
+ }
+ m_cmdline = new char [cmdline.length() + 1];
+ if (m_cmdline)
+ {
+ strcpy(m_cmdline, cmdline.c_str());
+ ParseCmdLine();
+ }
+ }
+
+ ~CmdLineArgs()
+ {
+ delete[] m_cmdline;
+ }
+
+private:
+ PSZ m_cmdline; // the command line string
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Parse m_cmdline into individual tokens, which are delimited by spaces. If a
+ // token begins with a quote, then that token is terminated by the next quote
+ // followed immediately by a space or terminator. This allows tokens to contain
+ // spaces.
+ // This input string: This "is" a ""test"" "of the parsing" alg"o"rithm.
+ // Produces these tokens: This, is, a, "test", of the parsing, alg"o"rithm
+ ////////////////////////////////////////////////////////////////////////////////
+ void ParseCmdLine ()
+ {
+ enum { TERM = '\0',
+ QUOTE = '\"' };
+
+ bool bInQuotes = false;
+ PSZ pargs = m_cmdline;
+
+ while (*pargs)
+ {
+ while (isspace (*pargs)) // skip leading whitespace
+ pargs++;
+
+ bInQuotes = (*pargs == QUOTE); // see if this token is quoted
+
+ if (bInQuotes) // skip leading quote
+ pargs++;
+
+ push_back (pargs); // store position of current token
+
+ // Find next token.
+ // NOTE: Args are normally terminated by whitespace, unless the
+ // arg is quoted. That's why we handle the two cases separately,
+ // even though they are very similar.
+ if (bInQuotes)
+ {
+ // find next quote followed by a space or terminator
+ while (*pargs &&
+ !(*pargs == QUOTE && (isspace (pargs[1]) || pargs[1] == TERM)))
+ pargs++;
+ if (*pargs)
+ {
+ *pargs = TERM; // terminate token
+ if (pargs[1]) // if quoted token not followed by a terminator
+ pargs += 2; // advance to next token
+ }
+ }
+ else
+ {
+ // skip to next non-whitespace character
+ while (*pargs && !isspace (*pargs))
+ pargs++;
+ if (*pargs && isspace (*pargs)) // end of token
+ {
+ *pargs = TERM; // terminate token
+ pargs++; // advance to next token or terminator
+ }
+ }
+ } // while (*pargs)
+ } // ParseCmdLine()
+}; // class CmdLineArgs
+
+
+#endif // CMDLINEARGS_H
diff --git a/tools/XBMCTexXBT/xwinapi.cpp b/tools/XBMCTexXBT/xwinapi.cpp
new file mode 100644
index 0000000000..ea5955c837
--- /dev/null
+++ b/tools/XBMCTexXBT/xwinapi.cpp
@@ -0,0 +1,81 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include "xwinapi.h"
+#ifdef __APPLE__
+#include "OSXGNUReplacements.h"
+#endif
+
+// I hope this doesn't need to handle unicode...
+LPTSTR GetCommandLine() {
+ pid_t pid = 0;
+ char procFile[32],
+ *cmdline = NULL;
+ FILE *fp = NULL;
+ size_t cmdlinelen = 0;
+ int i;
+
+ pid = getpid();
+ sprintf(procFile, "/proc/%u/cmdline", pid);
+ if((fp = fopen(procFile, "r")) == NULL)
+ return NULL;
+
+ // getline() allocates memory so be sure to free it
+ // after calling GetCommandLine()
+ if (getline(&cmdline, &cmdlinelen, fp) == -1)
+ {
+ fclose(fp);
+ return NULL;
+ }
+
+ fclose(fp);
+ fp = NULL;
+
+ for (i = 0; i < (int)cmdlinelen; i++) {
+ if (cmdline[i] == 0x00) {
+ if (cmdline[i + 1] == 0x00)
+ break;
+ cmdline[i] = ' ';
+ }
+ }
+
+ cmdline = (char *)realloc(cmdline, strlen(cmdline) + 1);
+ return cmdline;
+}
+
+DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer) {
+ bool bSizeTest = (nBufferLength == 0 && lpBuffer == NULL);
+ if (getcwd(lpBuffer, nBufferLength) == NULL) {
+ if (errno == ERANGE) {
+ LPTSTR tmp = NULL;
+ if (getcwd(tmp, 0) == NULL )
+ nBufferLength = 0;
+ else
+ nBufferLength = strlen(tmp) + 1;
+
+ free(tmp);
+ return nBufferLength;
+ }
+ return 0;
+ }
+ if (bSizeTest) {
+ nBufferLength = strlen(lpBuffer) + 1;
+ free(lpBuffer);
+ lpBuffer = NULL;
+ return nBufferLength;
+ }
+ return strlen(lpBuffer);
+}
+
+BOOL SetCurrentDirectory(LPCTSTR lpPathName) {
+ return (chdir(lpPathName) == 0);
+}
+
+DWORD GetLastError( ) {
+ return errno;
+}
+
diff --git a/tools/XBMCTexXBT/xwinapi.h b/tools/XBMCTexXBT/xwinapi.h
new file mode 100644
index 0000000000..be97e4c00a
--- /dev/null
+++ b/tools/XBMCTexXBT/xwinapi.h
@@ -0,0 +1,11 @@
+#ifndef XWINAPI_H__
+#define XWINAPI_H__
+
+#include "PlatformDefs.h"
+
+LPTSTR GetCommandLine();
+DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer);
+BOOL SetCurrentDirectory(LPCTSTR lpPathName);
+DWORD GetLastError();
+#endif // XWINAPI_H__
+
diff --git a/xbmc/Picture.cpp b/xbmc/Picture.cpp
index 7aec6ed080..55b3c0cfa0 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);
+ pTexture->Allocate(m_info.width, m_info.height, 32, XB_FMT_B8G8R8A8);
if (pTexture)
{
diff --git a/xbmc/RenderSystem.h b/xbmc/RenderSystem.h
index 024881b06a..d2672b2033 100644
--- a/xbmc/RenderSystem.h
+++ b/xbmc/RenderSystem.h
@@ -74,6 +74,7 @@ public:
virtual void GetViewPort(CRect& viewPort) = 0;
virtual bool NeedPower2Texture() = 0;
+ virtual bool SupportsCompressedTextures() = 0;
virtual void CaptureStateBlock() = 0;
virtual void ApplyStateBlock() = 0;
diff --git a/xbmc/RenderSystemDX.h b/xbmc/RenderSystemDX.h
index 7aa305a867..35bdb3d540 100644
--- a/xbmc/RenderSystemDX.h
+++ b/xbmc/RenderSystemDX.h
@@ -52,6 +52,7 @@ public:
virtual void GetViewPort(CRect& viewPort);
virtual bool NeedPower2Texture() { return m_NeedPower2Texture; }
+ virtual bool SupportsCompressedTextures() { return false; /* TODO: temporary until we add support for compressed textures in DX */ }
virtual void CaptureStateBlock();
virtual void ApplyStateBlock();
diff --git a/xbmc/RenderSystemGL.cpp b/xbmc/RenderSystemGL.cpp
index 4c0ac85375..18f28be320 100644
--- a/xbmc/RenderSystemGL.cpp
+++ b/xbmc/RenderSystemGL.cpp
@@ -68,7 +68,7 @@ bool CRenderSystemGL::InitRenderSystem()
// Check if we need DPOT
m_NeedPower2Texture = true;
- if (m_RenderVerdenVersionMajor >= 2 && GLEW_ARB_texture_non_power_of_two)
+ if (GLEW_ARB_texture_non_power_of_two)
m_NeedPower2Texture = false;
// Get our driver vendor and renderer
@@ -433,4 +433,9 @@ void CRenderSystemGL::SetViewPort(CRect& viewPort)
glViewport((GLint) viewPort.x1, (GLint) (m_height - viewPort.y1 - viewPort.Height()), (GLsizei) viewPort.Width(), (GLsizei) viewPort.Height());
}
+bool CRenderSystemGL::SupportsCompressedTextures()
+{
+ return glewIsSupported("GL_EXT_texture_compression_s3tc");
+}
+
#endif
diff --git a/xbmc/RenderSystemGL.h b/xbmc/RenderSystemGL.h
index f51bf1342e..255472ac22 100644
--- a/xbmc/RenderSystemGL.h
+++ b/xbmc/RenderSystemGL.h
@@ -50,6 +50,7 @@ public:
virtual void GetViewPort(CRect& viewPort);
virtual bool NeedPower2Texture() { return m_NeedPower2Texture; }
+ virtual bool SupportsCompressedTextures();
virtual void CaptureStateBlock();
virtual void ApplyStateBlock();
diff --git a/xbmc/karaoke/karaokelyricscdg.cpp b/xbmc/karaoke/karaokelyricscdg.cpp
index 8baadd7ec6..3cc19452d7 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 * HEIGHT );
- m_pCdgTexture->Update( WIDTH, HEIGHT, WIDTH * 4, buf, false );
+ m_pCdgTexture->Update( WIDTH, HEIGHT, WIDTH * 4, XB_FMT_B8G8R8A8, buf, false );
}
delete [] buf;