Index: guilib/guilib.vcproj =================================================================== --- guilib/guilib.vcproj (revision 30756) +++ guilib/guilib.vcproj (working copy) @@ -675,6 +675,9 @@ RelativePath=".\VisibleEffect.h"> + + Index: xbmc.vcproj =================================================================== --- xbmc.vcproj (revision 30756) +++ xbmc.vcproj (working copy) @@ -886,6 +886,12 @@ RelativePath=".\xbmc\DateTime.cpp"> + + + + + + +#include "FileSystem/File.h" +using namespace XFILE; + +using namespace std; + +CDDSImage::CDDSImage() +{ + m_data = NULL; + memset(&m_desc, 0, sizeof(m_desc)); +} + +CDDSImage::CDDSImage(unsigned int width, unsigned int height, unsigned int format) +{ + m_data = NULL; + Allocate(width, height, format); +} + +CDDSImage::~CDDSImage() +{ + delete[] m_data; +} + +/* + If dds file is marked with our magic mark, read orgWidth and orgHeight, otherwise we read + normal width and height (file is a standard dds file and does not contain our modification. + See DDSImage.h for details. +*/ + +unsigned int CDDSImage::GetOrgWidth() const +{ + return (m_desc.xbmcMagic == DD_XBMC_MAGIC) ? m_desc.orgWidth : m_desc.width; +} + +unsigned int CDDSImage::GetOrgHeight() const +{ + return (m_desc.xbmcMagic == DD_XBMC_MAGIC) ? m_desc.orgHeight : m_desc.height; +} + +unsigned int CDDSImage::GetWidth() const +{ + return m_desc.width; +} + +unsigned int CDDSImage::GetHeight() const +{ + return m_desc.height; +} + +unsigned int CDDSImage::GetFormat() const +{ + if (m_desc.pixelFormat.flags & DDPF_RGB) + return 0; // Not supported + if (m_desc.pixelFormat.flags & DDPF_FOURCC) + { + if (strncmp((const char *)&m_desc.pixelFormat.fourcc, "DXT1", 4) == 0) + return XB_FMT_DXT1; + /* + //We are only supporting DXT1 at this time. + + if (strncmp((const char *)&m_desc.pixelFormat.fourcc, "DXT3", 4) == 0) + return XB_FMT_DXT3; + if (strncmp((const char *)&m_desc.pixelFormat.fourcc, "DXT5", 4) == 0) + return XB_FMT_DXT5; + if (strncmp((const char *)&m_desc.pixelFormat.fourcc, "ARGB", 4) == 0) + return XB_FMT_A8R8G8B8; + + */ + } + return 0; +} + +unsigned int CDDSImage::GetSize() const +{ + return m_desc.linearSize; +} + +unsigned char *CDDSImage::GetData() const +{ + return m_data; +} + +bool CDDSImage::ReadFile(const std::string &inputFile) +{ + // open the file + CFile file; + if (!file.Open(inputFile)) + { + CLog::Log(LOGERROR, "%s - CFile.Open failed %s", __FUNCTION__, inputFile.c_str()); + return false; + } + + // read the header + uint32_t magic; + if (file.Read(&magic, 4) != 4) + { + CLog::Log(LOGERROR, "%s - Magic Header not found %s", __FUNCTION__, inputFile.c_str()); + return false; + } + if (file.Read(&m_desc, sizeof(m_desc)) != sizeof(m_desc)) + { + CLog::Log(LOGERROR, "%s - Description Invalid %s", __FUNCTION__, inputFile.c_str()); + return false; + } + if (!GetFormat()) + { + CLog::Log(LOGERROR, "%s - GetFormat returned false %s", __FUNCTION__, inputFile.c_str()); + return false; // not supported + } + + //This is temporary to make sure a "generic" .dds file is not read in at this point + //This can get removed once a proper routine is written to dynamically pad to POT (if deemed + //that such support is needed) + if (m_desc.xbmcMagic != DD_XBMC_MAGIC) + { + CLog::Log(LOGERROR, "%s - DDS file was not marked for xbmc use %s", __FUNCTION__, inputFile.c_str()); + return false; // not supported + } + + // allocate our data + m_data = new unsigned char[m_desc.linearSize]; + if (!m_data) + { + CLog::Log(LOGERROR, "%s - No Data %s", __FUNCTION__, inputFile.c_str()); + return false; + } + + // and read it in + if (file.Read(m_data, m_desc.linearSize) != m_desc.linearSize) + { + CLog::Log(LOGERROR, "%s - Data doesn't match header size %s", __FUNCTION__, inputFile.c_str()); + return false; + } + + file.Close(); + return true; +} + +bool CDDSImage::WriteFile(const std::string &outputFile) const +{ + // open the file + CFile file; + if (!file.OpenForWrite(outputFile, true)) + return false; + + // write the header + file.Write("DDS ", 4); + file.Write(&m_desc, sizeof(m_desc)); + // now the data + file.Write(m_data, m_desc.linearSize); + file.Close(); + return true; +} + +unsigned int CDDSImage::GetStorageRequirements(unsigned int width, unsigned int height, unsigned int format) const +{ + switch (format) + { + case XB_FMT_DXT1: + return ((width + 3) / 4) * ((height + 3) / 4) * 8; + case XB_FMT_DXT3: + case XB_FMT_DXT5: + return ((width + 3) / 4) * ((height + 3) / 4) * 16; + case XB_FMT_A8R8G8B8: + default: + return width * height * 4; + } +} + +void CDDSImage::Allocate(unsigned int width, unsigned int height, unsigned int format) +{ + memset(&m_desc, 0, sizeof(m_desc)); + m_desc.size = sizeof(m_desc); + m_desc.flags = ddsd_caps | ddsd_pixelformat | ddsd_width | ddsd_height | ddsd_linearsize; + m_desc.height = height; + m_desc.width = width; + m_desc.linearSize = GetStorageRequirements(width, height, format); + m_desc.pixelFormat.size = sizeof(m_desc.pixelFormat); + m_desc.pixelFormat.flags = ddpf_fourcc; + memcpy(&m_desc.pixelFormat.fourcc, GetFourCC(format), 4); + m_desc.caps.flags1 = ddscaps_texture; + delete[] m_data; + m_data = new unsigned char[m_desc.linearSize]; +} + +const char *CDDSImage::GetFourCC(unsigned int format) const +{ + switch (format) + { + case XB_FMT_DXT1: + return "DXT1"; + case XB_FMT_DXT3: + return "DXT3"; + case XB_FMT_DXT5: + return "DXT5"; + case XB_FMT_A8R8G8B8: + default: + return "ARGB"; + } +} Index: xbmc/DDSImage.h =================================================================== --- xbmc/DDSImage.h (revision 0) +++ xbmc/DDSImage.h (revision 0) @@ -0,0 +1,140 @@ +/* + * 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 + * + */ + +#pragma once + +#include +#include + +class CDDSImage +{ +public: + CDDSImage(); + CDDSImage(unsigned int width, unsigned int height, unsigned int format); + ~CDDSImage(); + + unsigned int GetOrgWidth() const; + unsigned int GetOrgHeight() const; + unsigned int GetWidth() const; + unsigned int GetHeight() const; + unsigned int GetFormat() const; + unsigned int GetSize() const; + unsigned char *GetData() const; + + bool ReadFile(const std::string &file); + +private: + void Allocate(unsigned int width, unsigned int height, unsigned int format); + const char *GetFourCC(unsigned int format) const; + bool WriteFile(const std::string &file) const; + unsigned int GetStorageRequirements(unsigned int width, unsigned int height, unsigned int format) const; + enum { + ddsd_caps = 0x00000001, + ddsd_height = 0x00000002, + ddsd_width = 0x00000004, + ddsd_pitch = 0x00000008, + ddsd_pixelformat = 0x00001000, + ddsd_mipmapcount = 0x00020000, + ddsd_linearsize = 0x00080000, + ddsd_depth = 0x00800000 + }; + + enum { + ddpf_alphapixels = 0x00000001, + ddpf_fourcc = 0x00000004, + ddpf_rgb = 0x00000040 + }; + + enum { + ddscaps_complex = 0x00000008, + ddscaps_texture = 0x00001000, + ddscaps_mipmap = 0x00400000 + }; + + #pragma pack(push, 2) + typedef struct + { + uint32_t size; + uint32_t flags; + uint32_t fourcc; + uint32_t rgbBitCount; + uint32_t rBitMask; + uint32_t gBitMask; + uint32_t bBitMask; + uint32_t aBitMask; + } ddpixelformat; + +#define DDPF_ALPHAPIXELS 0x00000001 +#define DDPF_ALPHA 0x00000002 +#define DDPF_FOURCC 0x00000004 +#define DDPF_RGB 0x00000040 +#define DDPF_YUV 0x00000200 +#define DDPF_LUMINANCE 0x00020000 + +//XBMC Magic Mark 0x434D4258 = 'XBMC' +#define DD_XBMC_MAGIC 0x434D4258 + + typedef struct + { + uint32_t flags1; + uint32_t flags2; + uint32_t reserved[2]; + } ddcaps2; + + typedef struct + { + uint32_t size; + uint32_t flags; + uint32_t height; + uint32_t width; + uint32_t linearSize; + uint32_t depth; + uint32_t mipmapcount; + /* + DDS FILE FORMAT MODIFICATION FOR PRE-PADDED TEXTURES + + Original reserved area: + uint32_t reserved[11]; + + This modification uses the last 3 dwords of space in the 1st reserved area to store + the actual size of the image data (as opposed to the texture size). The DDS file + format was not designed to be used pre-padded - this modification was necessary + in order to support it. Having the textures pre-padded on disk saves quite a bit of + work, since otherwise we would have to manually pad the texture to POT procedurally + and then clamp the edges off - this allows us to avoid that. See GetOrgWidth() and + GetOrgHeight() in DDSImage.cpp + */ + uint32_t reserved[8]; + uint32_t xbmcMagic; + uint32_t orgWidth; + uint32_t orgHeight; + /* + END DDS FILE FORMAT MODIFICATION + */ + ddpixelformat pixelFormat; + ddcaps2 caps; + uint32_t reserved2; + } ddsurfacedesc2; + #pragma pack(pop) + + ddsurfacedesc2 m_desc; + unsigned char *m_data; +}; Index: xbmc/Picture.cpp =================================================================== --- xbmc/Picture.cpp (revision 30756) +++ xbmc/Picture.cpp (working copy) @@ -27,8 +27,11 @@ #include "FileItem.h" #include "FileSystem/File.h" #include "FileSystem/FileCurl.h" +#include "DDSImage.h" #include "Util.h" #include "Crc32.h" +#include +#include "d3dx8.h" using namespace XFILE; @@ -44,6 +47,58 @@ IDirect3DTexture8* CPicture::Load(const CStdString& strFileName, int iMaxWidth, int iMaxHeight) { + /* + DDS files are not yet generated by xbmc. This setting simply enables support required + to render them properly. They must be created offline currently. We are currently only + supporting DXT1 format with no mipmaps that are generated by a utility that marks them + correctly for use by xbmc. These DDS files are pre-padded to POT to simplify/speedup + handling. + */ + if (g_advancedSettings.m_useddsfanart) + { + //If a .dds version of the image exists we load it instead. + CStdString ddsPath = CUtil::ReplaceExtension(strFileName, ".dds"); + if (CFile::Exists(ddsPath)) + { + CDDSImage img; + if (img.ReadFile(ddsPath)) + { + memset(&m_info, 0, sizeof(ImageInfo)); + /* + GetOrgWidth() and GetOrgHeight() return the actual size of the image stored in the dds file, + as opposed to the texture size (which is always POT) + */ + m_info.originalwidth = m_info.width = img.GetOrgWidth(); + m_info.originalheight = m_info.height = img.GetOrgHeight(); + LPDIRECT3DTEXTURE8 pTexture = NULL; + //Texture is created using GetWidth and GetHeight, which return texture size (always POT) + g_graphicsContext.Get3DDevice()->CreateTexture(img.GetWidth(), img.GetHeight(), 1, 0, D3DFMT_DXT1 , D3DPOOL_MANAGED, &pTexture); + if (pTexture) + { + D3DLOCKED_RECT lr; + if ( D3D_OK == pTexture->LockRect( 0, &lr, NULL, 0 )) + { + BYTE *pixels = (BYTE *)lr.pBits; + //DDS Textures are always POT and don't need decoding, just memcpy into the texture. + memcpy(pixels, img.GetData(), img.GetSize()); + pTexture->UnlockRect( 0 ); + } + return pTexture; + } + else + { + CLog::Log(LOGERROR, "%s - failed to create texture from dds image %s", __FUNCTION__, ddsPath.c_str()); + //fall through to default image loading code + } + } + else + { + CLog::Log(LOGERROR, "%s - could not read dds image %s", __FUNCTION__, ddsPath.c_str()); + //fall through to default image loading code + } + } + } + if (!m_dll.Load()) return NULL; memset(&m_info, 0, sizeof(ImageInfo)); @@ -83,6 +138,7 @@ CLog::Log(LOGERROR, "%s - failed to create texture while loading image %s", __FUNCTION__, strFileName.c_str()); m_dll.ReleaseImage(&m_info); return pTexture; + } bool CPicture::CreateThumbnail(const CStdString& file, const CStdString& thumbFile, bool checkExistence /*= false*/) Index: xbmc/XBTF.h =================================================================== --- xbmc/XBTF.h (revision 0) +++ xbmc/XBTF.h (revision 0) @@ -0,0 +1,100 @@ +/* + * 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 +#include +#include + +#define XBTF_MAGIC "XBTF" +#define XBTF_VERSION "2" + +#define XB_FMT_DXT_MASK 15 +#define XB_FMT_UNKNOWN 0 +#define XB_FMT_DXT1 1 +#define XB_FMT_DXT3 2 +#define XB_FMT_DXT5 4 +#define XB_FMT_DXT5_YCoCg 8 +#define XB_FMT_A8R8G8B8 16 +#define XB_FMT_A8 32 + +class CXBTFFrame +{ +public: + CXBTFFrame(); + uint32_t GetWidth() const; + void SetWidth(uint32_t width); + uint32_t GetFormat() const; + void SetFormat(uint32_t format); + uint32_t GetHeight() const; + void SetHeight(uint32_t height); + uint64_t GetUnpackedSize() const; + void SetUnpackedSize(uint64_t size); + uint64_t GetPackedSize() const; + void SetPackedSize(uint64_t size); + uint64_t GetOffset() const; + void SetOffset(uint64_t offset); + uint64_t GetHeaderSize() const; + uint32_t GetDuration() const; + void SetDuration(uint32_t duration); + bool IsPacked() const; + +private: + uint32_t m_width; + uint32_t m_height; + uint32_t m_format; + uint64_t m_packedSize; + uint64_t m_unpackedSize; + uint64_t m_offset; + uint32_t m_duration; +}; + +class CXBTFFile +{ +public: + CXBTFFile(); + CXBTFFile(const CXBTFFile& ref); + char* GetPath(); + void SetPath(const std::string& path); + uint32_t GetLoop() const; + void SetLoop(uint32_t loop); + std::vector& GetFrames(); + uint64_t GetHeaderSize() const; + +private: + char m_path[256]; + uint32_t m_loop; + std::vector m_frames; +}; + +class CXBTF +{ +public: + CXBTF(); + uint64_t GetHeaderSize() const; + std::vector& GetFiles(); + +private: + std::vector m_files; +}; + +#endif