Bug #150 ยป dds-support.patch
guilib/guilib.vcproj (working copy) | ||
---|---|---|
RelativePath=".\VisibleEffect.h">
|
||
</File>
|
||
<File
|
||
RelativePath=".\XBTF.h">
|
||
</File>
|
||
<File
|
||
RelativePath=".\XMLUtils.h">
|
||
</File>
|
||
</Filter>
|
xbmc.vcproj (working copy) | ||
---|---|---|
RelativePath=".\xbmc\DateTime.cpp">
|
||
</File>
|
||
<File
|
||
RelativePath=".\xbmc\DDSImage.cpp">
|
||
</File>
|
||
<File
|
||
RelativePath=".\xbmc\DDSImage.h">
|
||
</File>
|
||
<File
|
||
RelativePath=".\xbmc\utils\DelayController.cpp">
|
||
</File>
|
||
<File
|
||
... | ... | |
RelativePath=".\xbmc\XBInputEx.cpp">
|
||
</File>
|
||
<File
|
||
RelativePath=".\xbmc\XBTF.h">
|
||
</File>
|
||
<File
|
||
RelativePath=".\xbmc\XBTimeZone.cpp">
|
||
</File>
|
||
<File
|
xbmc/AdvancedSettings.cpp (working copy) | ||
---|---|---|
m_thumbSize = 192;
|
||
m_fanartHeight = 480;
|
||
m_useddsfanart = false;
|
||
m_sambaclienttimeout = 10;
|
||
m_sambadoscodepage = "";
|
||
... | ... | |
XMLUtils::GetFloat(pRootElement, "controllerdeadzone", m_controllerDeadzone, 0.0f, 1.0f);
|
||
XMLUtils::GetInt(pRootElement, "thumbsize", m_thumbSize, 0, 1024);
|
||
XMLUtils::GetInt(pRootElement, "fanartheight", m_fanartHeight, 0, 1080);
|
||
//dds support
|
||
XMLUtils::GetBoolean(pRootElement, "useddsfanart", m_useddsfanart);
|
||
XMLUtils::GetBoolean(pRootElement, "playlistasfolders", m_playlistAsFolders);
|
||
XMLUtils::GetBoolean(pRootElement, "detectasudf", m_detectAsUdf);
|
||
xbmc/AdvancedSettings.h (working copy) | ||
---|---|---|
int m_thumbSize;
|
||
int m_fanartHeight;
|
||
//dds DXT1 support
|
||
bool m_useddsfanart;
|
||
int m_sambaclienttimeout;
|
||
CStdString m_sambadoscodepage;
|
xbmc/DDSImage.cpp (revision 0) | ||
---|---|---|
/*
|
||
* 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 "DDSImage.h"
|
||
#include "XBTF.h"
|
||
#include "Util.h"
|
||
#include <string.h>
|
||
#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";
|
||
}
|
||
}
|
xbmc/DDSImage.h (revision 0) | ||
---|---|---|
/*
|
||
* 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 <string>
|
||
#include <stdint.h>
|
||
|
||
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;
|
||
};
|
xbmc/Picture.cpp (working copy) | ||
---|---|---|
#include "FileItem.h"
|
||
#include "FileSystem/File.h"
|
||
#include "FileSystem/FileCurl.h"
|
||
#include "DDSImage.h"
|
||
#include "Util.h"
|
||
#include "Crc32.h"
|
||
#include <XGraphics.h>
|
||
#include "d3dx8.h"
|
||
using namespace XFILE;
|
||
... | ... | |
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));
|
||
... | ... | |
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*/)
|
xbmc/XBTF.h (revision 0) | ||
---|---|---|
/*
|
||
* 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>
|
||
#include <stdint.h>
|
||
#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<CXBTFFrame>& GetFrames();
|
||
uint64_t GetHeaderSize() const;
|
||
private:
|
||
char m_path[256];
|
||
uint32_t m_loop;
|
||
std::vector<CXBTFFrame> m_frames;
|
||
};
|
||
class CXBTF
|
||
{
|
||
public:
|
||
CXBTF();
|
||
uint64_t GetHeaderSize() const;
|
||
std::vector<CXBTFFile>& GetFiles();
|
||
private:
|
||
std::vector<CXBTFFile> m_files;
|
||
};
|
||
#endif
|