Project

General

Profile

Bug #150 ยป dds-support.patch

galvanash, 18/12/2010 09:35 PM

View differences:

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
    (1-1/1)