Cleanup tex_codec, fixes #2456, patch by IronNerd.
This was SVN commit r14836.
This commit is contained in:
parent
a5639631ee
commit
ef888367aa
@ -38,14 +38,10 @@ public:
|
||||
m_VFS = CreateVfs(20*MiB);
|
||||
TS_ASSERT_OK(m_VFS->Mount(L"", DataDir()/"mods"/"_test.tex", VFS_MOUNT_MUST_EXIST));
|
||||
TS_ASSERT_OK(m_VFS->Mount(L"cache/", DataDir()/"_testcache"));
|
||||
|
||||
tex_codec_register_all();
|
||||
}
|
||||
|
||||
void tearDown()
|
||||
{
|
||||
tex_codec_unregister_all();
|
||||
|
||||
m_VFS.reset();
|
||||
DeleteDirectory(DataDir()/"_testcache");
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ public:
|
||||
TS_ASSERT_OK(m_VFS->Mount(L"cache/", DataDir()/"_testcache"));
|
||||
|
||||
h_mgr_init();
|
||||
tex_codec_register_all();
|
||||
|
||||
CXeromyces::Startup();
|
||||
}
|
||||
@ -50,7 +49,6 @@ public:
|
||||
{
|
||||
CXeromyces::Terminate();
|
||||
|
||||
tex_codec_unregister_all();
|
||||
h_mgr_shutdown();
|
||||
|
||||
m_VFS.reset();
|
||||
|
@ -64,74 +64,6 @@ class TestTex : public CxxTest::TestSuite
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// this also covers BGR and orientation transforms.
|
||||
void DISABLED_test_encode_decode() // disabled because it's completely broken
|
||||
{
|
||||
tex_codec_register_all();
|
||||
|
||||
// for each codec
|
||||
const TexCodecVTbl* c = 0;
|
||||
for(;;)
|
||||
{
|
||||
c = tex_codec_next(c);
|
||||
if(!c)
|
||||
break;
|
||||
|
||||
// get an extension that this codec will support
|
||||
// (so that tex_encode uses this codec)
|
||||
wchar_t extension[30] = {'.'};
|
||||
wcscpy_s(extension+1, 29, c->name);
|
||||
// .. make sure the c->name hack worked
|
||||
const TexCodecVTbl* correct_c = 0;
|
||||
TS_ASSERT_OK(tex_codec_for_filename(extension, &correct_c));
|
||||
TS_ASSERT_EQUALS(c, correct_c);
|
||||
|
||||
// for each test width/height combination
|
||||
const size_t widths [] = { 4, 5, 4, 256, 384 };
|
||||
const size_t heights[] = { 4, 4, 5, 256, 256 };
|
||||
for(size_t i = 0; i < ARRAY_SIZE(widths); i++)
|
||||
{
|
||||
// for each bit depth
|
||||
for(size_t bpp = 8; bpp <= 32; bpp += 8)
|
||||
{
|
||||
size_t flags = 0;
|
||||
if(!wcscmp(extension, L".dds"))
|
||||
flags |= (TEX_DXT&3); // DXT3
|
||||
if(bpp == 8)
|
||||
flags |= TEX_GREY;
|
||||
else if(bpp == 16)
|
||||
continue; // not supported
|
||||
else if(bpp == 32)
|
||||
flags |= TEX_ALPHA;
|
||||
|
||||
// normal
|
||||
generate_encode_decode_compare(widths[i], heights[i], flags, bpp, extension);
|
||||
// top-down
|
||||
flags &= ~TEX_ORIENTATION; flags |= TEX_TOP_DOWN;
|
||||
generate_encode_decode_compare(widths[i], heights[i], flags, bpp, extension);
|
||||
// bottom up
|
||||
flags &= ~TEX_ORIENTATION; flags |= TEX_BOTTOM_UP;
|
||||
generate_encode_decode_compare(widths[i], heights[i], flags, bpp, extension);
|
||||
|
||||
flags &= ~TEX_ORIENTATION;
|
||||
flags |= TEX_BGR;
|
||||
|
||||
// bgr, normal
|
||||
generate_encode_decode_compare(widths[i], heights[i], flags, bpp, extension);
|
||||
// bgr, top-down
|
||||
flags &= ~TEX_ORIENTATION; flags |= TEX_TOP_DOWN;
|
||||
generate_encode_decode_compare(widths[i], heights[i], flags, bpp, extension);
|
||||
// bgr, bottom up
|
||||
flags &= ~TEX_ORIENTATION; flags |= TEX_BOTTOM_UP;
|
||||
generate_encode_decode_compare(widths[i], heights[i], flags, bpp, extension);
|
||||
} // for bpp
|
||||
} // for width/height
|
||||
} // foreach codec
|
||||
|
||||
tex_codec_unregister_all();
|
||||
}
|
||||
|
||||
// have mipmaps be created for a test image; check resulting size and pixels
|
||||
void test_mipmap_create()
|
||||
{
|
||||
@ -164,8 +96,6 @@ public:
|
||||
|
||||
void test_s3tc_decode()
|
||||
{
|
||||
tex_codec_register_all();
|
||||
|
||||
const size_t w = 4, h = 4, bpp = 4;
|
||||
const size_t size = w*h/2;
|
||||
shared_ptr<u8> img(new u8[size], ArrayDeleter());
|
||||
@ -187,8 +117,5 @@ public:
|
||||
|
||||
// compare img
|
||||
TS_ASSERT_SAME_DATA(t.get_data(), expected, 48);
|
||||
|
||||
// cleanup
|
||||
tex_codec_unregister_all();
|
||||
}
|
||||
};
|
||||
|
@ -569,7 +569,7 @@ bool tex_orientations_match(size_t src_flags, size_t dst_orientation)
|
||||
// but this is open to misuse.
|
||||
bool tex_is_known_extension(const VfsPath& pathname)
|
||||
{
|
||||
const TexCodecVTbl* dummy;
|
||||
const ITexCodec* dummy;
|
||||
// found codec for it => known extension
|
||||
const OsPath extension = pathname.Extension();
|
||||
if(tex_codec_for_filename(extension, &dummy) == INFO::OK)
|
||||
@ -704,7 +704,7 @@ size_t Tex::img_size() const
|
||||
// directly into the output buffer and makes for zero-copy IO.
|
||||
size_t tex_hdr_size(const VfsPath& filename)
|
||||
{
|
||||
const TexCodecVTbl* c;
|
||||
const ITexCodec* c;
|
||||
|
||||
const OsPath extension = filename.Extension();
|
||||
WARN_RETURN_STATUS_IF_ERR(tex_codec_for_filename(extension, &c));
|
||||
@ -718,7 +718,7 @@ size_t tex_hdr_size(const VfsPath& filename)
|
||||
|
||||
Status Tex::decode(const shared_ptr<u8>& Data, size_t DataSize)
|
||||
{
|
||||
const TexCodecVTbl* c;
|
||||
const ITexCodec* c;
|
||||
RETURN_STATUS_IF_ERR(tex_codec_for_header(Data.get(), DataSize, &c));
|
||||
|
||||
// make sure the entire header is available
|
||||
@ -762,7 +762,7 @@ Status Tex::encode(const OsPath& extension, DynArray* da)
|
||||
const size_t max_out_size = img_size()*4 + 256*KiB;
|
||||
RETURN_STATUS_IF_ERR(da_alloc(da, max_out_size));
|
||||
|
||||
const TexCodecVTbl* c;
|
||||
const ITexCodec* c;
|
||||
WARN_RETURN_STATUS_IF_ERR(tex_codec_for_filename(extension, &c));
|
||||
|
||||
// encode into <da>
|
||||
|
@ -367,22 +367,6 @@ struct Tex
|
||||
extern void tex_set_global_orientation(int orientation);
|
||||
|
||||
|
||||
/**
|
||||
* Manually register codecs. must be called before first use of a
|
||||
* codec (e.g. loading a texture).
|
||||
*
|
||||
* This would normally be taken care of by TEX_CODEC_REGISTER, but
|
||||
* no longer works when building as a static library.
|
||||
* Workaround: hard-code a list of codecs in tex_codec.cpp and
|
||||
* call their registration functions.
|
||||
**/
|
||||
extern void tex_codec_register_all();
|
||||
|
||||
/**
|
||||
* remove all codecs that have been registered.
|
||||
**/
|
||||
extern void tex_codec_unregister_all();
|
||||
|
||||
/**
|
||||
* special value for levels_to_skip: the callback will only be called
|
||||
* for the base mipmap level (i.e. 100%)
|
||||
|
@ -60,13 +60,13 @@ struct BmpHeader
|
||||
#define BI_RGB 0 // biCompression
|
||||
|
||||
|
||||
static Status bmp_transform(Tex* UNUSED(t), size_t UNUSED(transforms))
|
||||
Status TexCodecBmp::transform(Tex* UNUSED(t), size_t UNUSED(transforms)) const
|
||||
{
|
||||
return INFO::TEX_CODEC_CANNOT_HANDLE;
|
||||
}
|
||||
|
||||
|
||||
static bool bmp_is_hdr(const u8* file)
|
||||
bool TexCodecBmp::is_hdr(const u8* file) const
|
||||
{
|
||||
// check header signature (bfType == "BM"?).
|
||||
// we compare single bytes to be endian-safe.
|
||||
@ -74,13 +74,13 @@ static bool bmp_is_hdr(const u8* file)
|
||||
}
|
||||
|
||||
|
||||
static bool bmp_is_ext(const OsPath& extension)
|
||||
bool TexCodecBmp::is_ext(const OsPath& extension) const
|
||||
{
|
||||
return extension == L".bmp";
|
||||
}
|
||||
|
||||
|
||||
static size_t bmp_hdr_size(const u8* file)
|
||||
size_t TexCodecBmp::hdr_size(const u8* file) const
|
||||
{
|
||||
const size_t hdr_size = sizeof(BmpHeader);
|
||||
if(file)
|
||||
@ -95,7 +95,7 @@ static size_t bmp_hdr_size(const u8* file)
|
||||
|
||||
|
||||
// requirements: uncompressed, direct colour, bottom up
|
||||
static Status bmp_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t)
|
||||
Status TexCodecBmp::decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t) const
|
||||
{
|
||||
const BmpHeader* hdr = (const BmpHeader*)data;
|
||||
const long w = (long)read_le32(&hdr->biWidth);
|
||||
@ -124,7 +124,7 @@ static Status bmp_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t)
|
||||
}
|
||||
|
||||
|
||||
static Status bmp_encode(Tex* RESTRICT t, DynArray* RESTRICT da)
|
||||
Status TexCodecBmp::encode(Tex* RESTRICT t, DynArray* RESTRICT da) const
|
||||
{
|
||||
const size_t hdr_size = sizeof(BmpHeader); // needed for BITMAPFILEHEADER
|
||||
const size_t img_size = t->img_size();
|
||||
@ -155,5 +155,3 @@ static Status bmp_encode(Tex* RESTRICT t, DynArray* RESTRICT da)
|
||||
};
|
||||
return tex_codec_write(t, transforms, &hdr, hdr_size, da);
|
||||
}
|
||||
|
||||
TEX_CODEC_REGISTER(bmp);
|
||||
|
@ -33,42 +33,30 @@
|
||||
#include "lib/allocators/shared_ptr.h" // ArrayDeleter
|
||||
#include "tex.h"
|
||||
|
||||
static const TexCodecVTbl* codecs;
|
||||
|
||||
// add this vtbl to the codec list. called at NLSO init time by the
|
||||
// TEX_CODEC_REGISTER in each codec file. note that call order and therefore
|
||||
// order in the list is undefined, but since each codec only steps up if it
|
||||
// can handle the given format, this is not a problem.
|
||||
//
|
||||
// returns int to alloc calling from a macro at file scope.
|
||||
int tex_codec_register(TexCodecVTbl* c)
|
||||
{
|
||||
ENSURE(c);
|
||||
|
||||
// insert at front of list.
|
||||
c->next = codecs;
|
||||
codecs = c;
|
||||
|
||||
return 0; // (assigned to dummy variable)
|
||||
}
|
||||
|
||||
// remove all codecs that have been registered.
|
||||
void tex_codec_unregister_all()
|
||||
{
|
||||
codecs = NULL;
|
||||
}
|
||||
// Statically allocate all of the codecs...
|
||||
TexCodecDds DdsCodec;
|
||||
TexCodecPng PngCodec;
|
||||
TexCodecJpg JpgCodec;
|
||||
TexCodecTga TgaCodec;
|
||||
TexCodecPng BmpCodec;
|
||||
// Codecs will be searched in this order
|
||||
static const ITexCodec *codecs[] = {(ITexCodec *)&DdsCodec, (ITexCodec *)&PngCodec,
|
||||
(ITexCodec *)&JpgCodec, (ITexCodec *)&TgaCodec, (ITexCodec *)&BmpCodec};
|
||||
static const int codecs_len = sizeof(codecs) / sizeof(ITexCodec*);
|
||||
|
||||
// find codec that recognizes the desired output file extension,
|
||||
// or return ERR::TEX_UNKNOWN_FORMAT if unknown.
|
||||
// note: does not raise a warning because it is used by
|
||||
// tex_is_known_extension.
|
||||
Status tex_codec_for_filename(const OsPath& extension, const TexCodecVTbl** c)
|
||||
Status tex_codec_for_filename(const OsPath& extension, const ITexCodec** c)
|
||||
{
|
||||
for(*c = codecs; *c; *c = (*c)->next)
|
||||
for(int i = 0; i < codecs_len; ++i)
|
||||
{
|
||||
// we found it
|
||||
if((*c)->is_ext(extension))
|
||||
if(codecs[i]->is_ext(extension)) {
|
||||
*c = codecs[i];
|
||||
return INFO::OK;
|
||||
}
|
||||
}
|
||||
|
||||
return ERR::TEX_UNKNOWN_FORMAT; // NOWARN
|
||||
@ -76,42 +64,32 @@ Status tex_codec_for_filename(const OsPath& extension, const TexCodecVTbl** c)
|
||||
|
||||
|
||||
// find codec that recognizes the header's magic field
|
||||
Status tex_codec_for_header(const u8* file, size_t file_size, const TexCodecVTbl** c)
|
||||
Status tex_codec_for_header(const u8* file, size_t file_size, const ITexCodec** c)
|
||||
{
|
||||
// we guarantee at least 4 bytes for is_hdr to look at
|
||||
if(file_size < 4)
|
||||
WARN_RETURN(ERR::TEX_INCOMPLETE_HEADER);
|
||||
|
||||
for(*c = codecs; *c; *c = (*c)->next)
|
||||
|
||||
for(int i = 0; i < codecs_len; ++i)
|
||||
{
|
||||
// we found it
|
||||
if((*c)->is_hdr(file))
|
||||
if(codecs[i]->is_hdr(file)) {
|
||||
*c = codecs[i];
|
||||
return INFO::OK;
|
||||
}
|
||||
}
|
||||
|
||||
WARN_RETURN(ERR::TEX_UNKNOWN_FORMAT);
|
||||
}
|
||||
|
||||
|
||||
const TexCodecVTbl* tex_codec_next(const TexCodecVTbl* prev_codec)
|
||||
{
|
||||
// first time
|
||||
if(!prev_codec)
|
||||
return codecs;
|
||||
// middle of list: return next (can be 0 to indicate end of list)
|
||||
else
|
||||
return prev_codec->next;
|
||||
}
|
||||
|
||||
|
||||
Status tex_codec_transform(Tex* t, size_t transforms)
|
||||
{
|
||||
Status ret = INFO::TEX_CODEC_CANNOT_HANDLE;
|
||||
|
||||
// find codec that understands the data, and transform
|
||||
for(const TexCodecVTbl* c = codecs; c; c = c->next)
|
||||
for(int i = 0; i < codecs_len; ++i)
|
||||
{
|
||||
Status err = c->transform(t, transforms);
|
||||
Status err = codecs[i]->transform(t, transforms);
|
||||
// success
|
||||
if(err == INFO::OK)
|
||||
return INFO::OK;
|
||||
@ -131,17 +109,6 @@ Status tex_codec_transform(Tex* t, size_t transforms)
|
||||
// helper functions used by codecs
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void tex_codec_register_all()
|
||||
{
|
||||
#define REGISTER_CODEC(name) extern void name##_register(); name##_register()
|
||||
REGISTER_CODEC(bmp);
|
||||
REGISTER_CODEC(dds);
|
||||
REGISTER_CODEC(jpg);
|
||||
REGISTER_CODEC(png);
|
||||
REGISTER_CODEC(tga);
|
||||
#undef REGISTER_CODEC
|
||||
}
|
||||
|
||||
// allocate an array of row pointers that point into the given texture data.
|
||||
// <file_orientation> indicates whether the file format is top-down or
|
||||
// bottom-up; the row array is inverted if necessary to match global
|
||||
|
@ -36,8 +36,9 @@
|
||||
* 'template method'-style interface to increase code reuse and
|
||||
* simplify writing new codecs.
|
||||
**/
|
||||
struct TexCodecVTbl
|
||||
class ITexCodec
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* decode the file into a Tex structure.
|
||||
*
|
||||
@ -49,7 +50,7 @@ struct TexCodecVTbl
|
||||
* @param t output texture object
|
||||
* @return Status
|
||||
**/
|
||||
Status (*decode)(u8* data, size_t size, Tex* RESTRICT t);
|
||||
virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const = 0;
|
||||
|
||||
/**
|
||||
* encode the texture data into the codec's file format (in memory).
|
||||
@ -62,7 +63,7 @@ struct TexCodecVTbl
|
||||
* by the caller.
|
||||
* @return Status
|
||||
**/
|
||||
Status (*encode)(Tex* RESTRICT t, DynArray* RESTRICT da);
|
||||
virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const = 0;
|
||||
|
||||
/**
|
||||
* transform the texture's pixel format.
|
||||
@ -73,7 +74,7 @@ struct TexCodecVTbl
|
||||
* to its format; generic pixel format transforms are handled by
|
||||
* the caller.
|
||||
**/
|
||||
Status (*transform)(Tex* t, size_t transforms);
|
||||
virtual Status transform(Tex* t, size_t transforms) const = 0;
|
||||
|
||||
/**
|
||||
* indicate if the data appears to be an instance of this codec's header,
|
||||
@ -83,7 +84,7 @@ struct TexCodecVTbl
|
||||
* (this should be enough to examine the header's 'magic' field)
|
||||
* @return bool
|
||||
**/
|
||||
bool (*is_hdr)(const u8* file);
|
||||
virtual bool is_hdr(const u8* file) const = 0;
|
||||
|
||||
/**
|
||||
* is the extension that of a file format supported by this codec?
|
||||
@ -95,7 +96,7 @@ struct TexCodecVTbl
|
||||
* @param extension (including '.')
|
||||
* @return bool
|
||||
**/
|
||||
bool (*is_ext)(const OsPath& extension);
|
||||
virtual bool is_ext(const OsPath& extension) const = 0;
|
||||
|
||||
/**
|
||||
* return size of the file header supported by this codec.
|
||||
@ -106,59 +107,85 @@ struct TexCodecVTbl
|
||||
* variable-length fields.
|
||||
* @return size [bytes]
|
||||
**/
|
||||
size_t (*hdr_size)(const u8* file);
|
||||
virtual size_t hdr_size(const u8* file) const = 0;
|
||||
|
||||
/**
|
||||
* name of codec for debug purposes. typically set via TEX_CODEC_REGISTER.
|
||||
**/
|
||||
const wchar_t* name;
|
||||
virtual const wchar_t* get_name() const = 0;
|
||||
|
||||
/**
|
||||
* intrusive linked-list of codecs: more convenient than fixed-size
|
||||
* static storage.
|
||||
* set by caller; should be initialized to NULL.
|
||||
**/
|
||||
const TexCodecVTbl* next;
|
||||
virtual ~ITexCodec() {}
|
||||
};
|
||||
|
||||
class TexCodecPng:ITexCodec {
|
||||
public:
|
||||
virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
|
||||
virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
|
||||
virtual Status transform(Tex* t, size_t transforms) const;
|
||||
virtual bool is_hdr(const u8* file) const;
|
||||
virtual bool is_ext(const OsPath& extension) const;
|
||||
virtual size_t hdr_size(const u8* file) const;
|
||||
virtual const wchar_t* get_name() const {
|
||||
static const wchar_t *name = L"png";
|
||||
return name;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* build codec vtbl and register it. the codec will be queried for future
|
||||
* texture load requests. call order is undefined, but since each codec
|
||||
* only steps up if it can handle the given format, this is not a problem.
|
||||
*
|
||||
* @param name identifier of codec (not string!). used to bind 'member'
|
||||
* functions prefixed with it to the vtbl, and as the TexCodecVTbl name.
|
||||
* it should also mirror the default file extension (e.g. dds) -
|
||||
* this is relied upon (but verified) in the self-test.
|
||||
*
|
||||
* usage: at file scope within the source file containing the codec's methods.
|
||||
**/
|
||||
#define TEX_CODEC_REGISTER(name)\
|
||||
static TexCodecVTbl UID__ = \
|
||||
{\
|
||||
name##_decode, name##_encode, name##_transform,\
|
||||
name##_is_hdr, name##_is_ext, name##_hdr_size,\
|
||||
WIDEN(#name)\
|
||||
};\
|
||||
/*static int dummy = tex_codec_register(&vtbl);*/\
|
||||
/* note: when building as a static library, pre-main initializers */\
|
||||
/* will not run! as a workaround, we build an externally visible */\
|
||||
/* registration function that must be called via */\
|
||||
/* tex_codec_register_all - see comments there. */\
|
||||
void name##_register() { tex_codec_register(&UID__); }
|
||||
class TexCodecJpg:ITexCodec {
|
||||
public:
|
||||
virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
|
||||
virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
|
||||
virtual Status transform(Tex* t, size_t transforms) const;
|
||||
virtual bool is_hdr(const u8* file) const;
|
||||
virtual bool is_ext(const OsPath& extension) const;
|
||||
virtual size_t hdr_size(const u8* file) const;
|
||||
virtual const wchar_t* get_name() const {
|
||||
static const wchar_t *name = L"jpg";
|
||||
return name;
|
||||
};
|
||||
};
|
||||
|
||||
class TexCodecDds:ITexCodec {
|
||||
public:
|
||||
virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
|
||||
virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
|
||||
virtual Status transform(Tex* t, size_t transforms) const;
|
||||
virtual bool is_hdr(const u8* file) const;
|
||||
virtual bool is_ext(const OsPath& extension) const;
|
||||
virtual size_t hdr_size(const u8* file) const;
|
||||
virtual const wchar_t* get_name() const {
|
||||
static const wchar_t *name = L"dds";
|
||||
return name;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* add this vtbl to the codec list. called at NLSO init time by the
|
||||
* TEX_CODEC_REGISTER in each codec file.
|
||||
* order in list is unspecified; see TEX_CODEC_REGISTER.
|
||||
*
|
||||
* @param c pointer to vtbl.
|
||||
* @return int (allows calling from a macro at file scope; value is not used)
|
||||
**/
|
||||
extern int tex_codec_register(TexCodecVTbl* c);
|
||||
class TexCodecTga:ITexCodec {
|
||||
public:
|
||||
virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
|
||||
virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
|
||||
virtual Status transform(Tex* t, size_t transforms) const;
|
||||
virtual bool is_hdr(const u8* file) const;
|
||||
virtual bool is_ext(const OsPath& extension) const;
|
||||
virtual size_t hdr_size(const u8* file) const;
|
||||
virtual const wchar_t* get_name() const {
|
||||
static const wchar_t *name = L"tga";
|
||||
return name;
|
||||
};
|
||||
};
|
||||
|
||||
class TexCodecBmp:ITexCodec {
|
||||
public:
|
||||
virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
|
||||
virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
|
||||
virtual Status transform(Tex* t, size_t transforms) const;
|
||||
virtual bool is_hdr(const u8* file) const;
|
||||
virtual bool is_ext(const OsPath& extension) const;
|
||||
virtual size_t hdr_size(const u8* file) const;
|
||||
virtual const wchar_t* get_name() const {
|
||||
static const wchar_t *name = L"bmp";
|
||||
return name;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Find codec that recognizes the desired output file extension.
|
||||
@ -169,7 +196,7 @@ extern int tex_codec_register(TexCodecVTbl* c);
|
||||
* called by tex_is_known_extension) if no codec indicates they can
|
||||
* handle the given extension.
|
||||
**/
|
||||
extern Status tex_codec_for_filename(const OsPath& extension, const TexCodecVTbl** c);
|
||||
extern Status tex_codec_for_filename(const OsPath& extension, const ITexCodec** c);
|
||||
|
||||
/**
|
||||
* find codec that recognizes the header's magic field.
|
||||
@ -181,19 +208,7 @@ extern Status tex_codec_for_filename(const OsPath& extension, const TexCodecVTbl
|
||||
* @return Status; ERR::RES_UNKNOWN_FORMAT if no codec indicates they can
|
||||
* handle the given format (header).
|
||||
**/
|
||||
extern Status tex_codec_for_header(const u8* data, size_t data_size, const TexCodecVTbl** c);
|
||||
|
||||
/**
|
||||
* enumerate all registered codecs.
|
||||
*
|
||||
* used by self-test to test each one of them in turn.
|
||||
*
|
||||
* @param prev_codec the last codec returned by this function.
|
||||
* pass 0 the first time.
|
||||
* note: this routine is stateless and therefore reentrant.
|
||||
* @return the next codec, or 0 if all have been returned.
|
||||
**/
|
||||
extern const TexCodecVTbl* tex_codec_next(const TexCodecVTbl* prev_codec);
|
||||
extern Status tex_codec_for_header(const u8* data, size_t data_size, const ITexCodec** c);
|
||||
|
||||
/**
|
||||
* transform the texture's pixel format.
|
||||
|
@ -586,25 +586,25 @@ static Status decode_sd(const DDS_HEADER* sd, size_t& w, size_t& h, size_t& bpp,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static bool dds_is_hdr(const u8* file)
|
||||
bool TexCodecDds::is_hdr(const u8* file) const
|
||||
{
|
||||
return *(u32*)file == FOURCC('D','D','S',' ');
|
||||
}
|
||||
|
||||
|
||||
static bool dds_is_ext(const OsPath& extension)
|
||||
bool TexCodecDds::is_ext(const OsPath& extension) const
|
||||
{
|
||||
return extension == L".dds";
|
||||
}
|
||||
|
||||
|
||||
static size_t dds_hdr_size(const u8* UNUSED(file))
|
||||
size_t TexCodecDds::hdr_size(const u8* UNUSED(file)) const
|
||||
{
|
||||
return 4+sizeof(DDS_HEADER);
|
||||
}
|
||||
|
||||
|
||||
static Status dds_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t)
|
||||
Status TexCodecDds::decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t) const
|
||||
{
|
||||
const DDS_HEADER* sd = (const DDS_HEADER*)(data+4);
|
||||
RETURN_STATUS_IF_ERR(decode_sd(sd, t->m_Width, t->m_Height, t->m_Bpp, t->m_Flags));
|
||||
@ -612,7 +612,7 @@ static Status dds_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t)
|
||||
}
|
||||
|
||||
|
||||
static Status dds_encode(Tex* RESTRICT UNUSED(t), DynArray* RESTRICT UNUSED(da))
|
||||
Status TexCodecDds::encode(Tex* RESTRICT UNUSED(t), DynArray* RESTRICT UNUSED(da)) const
|
||||
{
|
||||
// note: do not return ERR::NOT_SUPPORTED et al. because that would
|
||||
// break tex_write (which assumes either this, 0 or errors are returned).
|
||||
@ -622,7 +622,7 @@ static Status dds_encode(Tex* RESTRICT UNUSED(t), DynArray* RESTRICT UNUSED(da))
|
||||
|
||||
TIMER_ADD_CLIENT(tc_dds_transform);
|
||||
|
||||
static Status dds_transform(Tex* t, size_t transforms)
|
||||
Status TexCodecDds::transform(Tex* t, size_t transforms) const
|
||||
{
|
||||
TIMER_ACCRUE(tc_dds_transform);
|
||||
|
||||
@ -651,6 +651,3 @@ static Status dds_transform(Tex* t, size_t transforms)
|
||||
// both not DXT (nothing we can do) - bail.
|
||||
return INFO::TEX_CODEC_CANNOT_HANDLE;
|
||||
}
|
||||
|
||||
|
||||
TEX_CODEC_REGISTER(dds);
|
||||
|
@ -423,7 +423,7 @@ JpgErrorMgr::JpgErrorMgr(jpeg_decompress_struct& cinfo)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
static Status jpg_transform(Tex* UNUSED(t), size_t UNUSED(transforms))
|
||||
Status TexCodecJpg::transform(Tex* UNUSED(t), size_t UNUSED(transforms)) const
|
||||
{
|
||||
return INFO::TEX_CODEC_CANNOT_HANDLE;
|
||||
}
|
||||
@ -557,7 +557,7 @@ static Status jpg_encode_impl(Tex* t, jpeg_compress_struct* cinfo, DynArray* da)
|
||||
|
||||
|
||||
|
||||
static bool jpg_is_hdr(const u8* file)
|
||||
bool TexCodecJpg::is_hdr(const u8* file) const
|
||||
{
|
||||
// JFIF requires SOI marker at start of stream.
|
||||
// we compare single bytes to be endian-safe.
|
||||
@ -565,19 +565,19 @@ static bool jpg_is_hdr(const u8* file)
|
||||
}
|
||||
|
||||
|
||||
static bool jpg_is_ext(const OsPath& extension)
|
||||
bool TexCodecJpg::is_ext(const OsPath& extension) const
|
||||
{
|
||||
return extension == L".jpg" || extension == L".jpeg";
|
||||
}
|
||||
|
||||
|
||||
static size_t jpg_hdr_size(const u8* UNUSED(file))
|
||||
size_t TexCodecJpg::hdr_size(const u8* UNUSED(file)) const
|
||||
{
|
||||
return 0; // libjpg returns decoded image data; no header
|
||||
}
|
||||
|
||||
|
||||
static Status jpg_decode(rpU8 data, size_t size, Tex* RESTRICT t)
|
||||
Status TexCodecJpg::decode(rpU8 data, size_t size, Tex* RESTRICT t) const
|
||||
{
|
||||
// contains the JPEG decompression parameters and pointers to
|
||||
// working space (allocated as needed by the JPEG library).
|
||||
@ -598,7 +598,7 @@ static Status jpg_decode(rpU8 data, size_t size, Tex* RESTRICT t)
|
||||
|
||||
|
||||
// limitation: palette images aren't supported
|
||||
static Status jpg_encode(Tex* RESTRICT t, DynArray* RESTRICT da)
|
||||
Status TexCodecJpg::encode(Tex* RESTRICT t, DynArray* RESTRICT da) const
|
||||
{
|
||||
// contains the JPEG compression parameters and pointers to
|
||||
// working space (allocated as needed by the JPEG library).
|
||||
@ -616,5 +616,3 @@ static Status jpg_encode(Tex* RESTRICT t, DynArray* RESTRICT da)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEX_CODEC_REGISTER(jpg);
|
||||
|
@ -107,7 +107,7 @@ static void io_flush(png_structp UNUSED(png_ptr))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static Status png_transform(Tex* UNUSED(t), size_t UNUSED(transforms))
|
||||
Status TexCodecPng::transform(Tex* UNUSED(t), size_t UNUSED(transforms)) const
|
||||
{
|
||||
return INFO::TEX_CODEC_CANNOT_HANDLE;
|
||||
}
|
||||
@ -200,7 +200,7 @@ static Status png_encode_impl(Tex* t, png_structp png_ptr, png_infop info_ptr, D
|
||||
|
||||
|
||||
|
||||
static bool png_is_hdr(const u8* file)
|
||||
bool TexCodecPng::is_hdr(const u8* file) const
|
||||
{
|
||||
// don't use png_sig_cmp, so we don't pull in libpng for
|
||||
// this check alone (it might not actually be used).
|
||||
@ -208,13 +208,13 @@ static bool png_is_hdr(const u8* file)
|
||||
}
|
||||
|
||||
|
||||
static bool png_is_ext(const OsPath& extension)
|
||||
bool TexCodecPng::is_ext(const OsPath& extension) const
|
||||
{
|
||||
return extension == L".png";
|
||||
}
|
||||
|
||||
|
||||
static size_t png_hdr_size(const u8* UNUSED(file))
|
||||
size_t TexCodecPng::hdr_size(const u8* UNUSED(file)) const
|
||||
{
|
||||
return 0; // libpng returns decoded image data; no header
|
||||
}
|
||||
@ -223,7 +223,7 @@ static size_t png_hdr_size(const u8* UNUSED(file))
|
||||
TIMER_ADD_CLIENT(tc_png_decode);
|
||||
|
||||
// limitation: palette images aren't supported
|
||||
static Status png_decode(rpU8 data, size_t size, Tex* RESTRICT t)
|
||||
Status TexCodecPng::decode(rpU8 data, size_t size, Tex* RESTRICT t) const
|
||||
{
|
||||
TIMER_ACCRUE(tc_png_decode);
|
||||
|
||||
@ -257,7 +257,7 @@ TIMER_ACCRUE(tc_png_decode);
|
||||
|
||||
|
||||
// limitation: palette images aren't supported
|
||||
static Status png_encode(Tex* RESTRICT t, DynArray* RESTRICT da)
|
||||
Status TexCodecPng::encode(Tex* RESTRICT t, DynArray* RESTRICT da) const
|
||||
{
|
||||
Status ret = ERR::FAIL;
|
||||
png_infop info_ptr = 0;
|
||||
@ -284,5 +284,3 @@ fail:
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEX_CODEC_REGISTER(png);
|
||||
|
@ -67,13 +67,13 @@ TgaHeader;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
static Status tga_transform(Tex* UNUSED(t), size_t UNUSED(transforms))
|
||||
Status TexCodecTga::transform(Tex* UNUSED(t), size_t UNUSED(transforms)) const
|
||||
{
|
||||
return INFO::TEX_CODEC_CANNOT_HANDLE;
|
||||
}
|
||||
|
||||
|
||||
static bool tga_is_hdr(const u8* file)
|
||||
bool TexCodecTga::is_hdr(const u8* file) const
|
||||
{
|
||||
TgaHeader* hdr = (TgaHeader*)file;
|
||||
|
||||
@ -93,13 +93,13 @@ static bool tga_is_hdr(const u8* file)
|
||||
}
|
||||
|
||||
|
||||
static bool tga_is_ext(const OsPath& extension)
|
||||
bool TexCodecTga::is_ext(const OsPath& extension) const
|
||||
{
|
||||
return extension == L".tga";
|
||||
}
|
||||
|
||||
|
||||
static size_t tga_hdr_size(const u8* file)
|
||||
size_t TexCodecTga::hdr_size(const u8* file) const
|
||||
{
|
||||
size_t hdr_size = sizeof(TgaHeader);
|
||||
if(file)
|
||||
@ -112,7 +112,7 @@ static size_t tga_hdr_size(const u8* file)
|
||||
|
||||
|
||||
// requirements: uncompressed, direct color, bottom up
|
||||
static Status tga_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t)
|
||||
Status TexCodecTga::decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t) const
|
||||
{
|
||||
const TgaHeader* hdr = (const TgaHeader*)data;
|
||||
const u8 type = hdr->img_type;
|
||||
@ -144,7 +144,7 @@ static Status tga_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t)
|
||||
}
|
||||
|
||||
|
||||
static Status tga_encode(Tex* RESTRICT t, DynArray* RESTRICT da)
|
||||
Status TexCodecTga::encode(Tex* RESTRICT t, DynArray* RESTRICT da) const
|
||||
{
|
||||
u8 img_desc = 0;
|
||||
if(t->m_Flags & TEX_TOP_DOWN)
|
||||
@ -173,4 +173,3 @@ static Status tga_encode(Tex* RESTRICT t, DynArray* RESTRICT da)
|
||||
return tex_codec_write(t, transforms, &hdr, hdr_size, da);
|
||||
}
|
||||
|
||||
TEX_CODEC_REGISTER(tga);
|
||||
|
@ -44,7 +44,6 @@ public:
|
||||
|
||||
// Need some stuff for terrain movement costs:
|
||||
// (TODO: this ought to be independent of any graphics code)
|
||||
tex_codec_register_all();
|
||||
new CTerrainTextureManager;
|
||||
g_TexMan.LoadTerrainTextures();
|
||||
|
||||
@ -56,7 +55,6 @@ public:
|
||||
enet_deinitialize();
|
||||
|
||||
delete &g_TexMan;
|
||||
tex_codec_unregister_all();
|
||||
|
||||
CXeromyces::Terminate();
|
||||
g_VFS.reset();
|
||||
|
@ -36,8 +36,6 @@
|
||||
CArchiveBuilder::CArchiveBuilder(const OsPath& mod, const OsPath& tempdir) :
|
||||
m_TempDir(tempdir)
|
||||
{
|
||||
tex_codec_register_all();
|
||||
|
||||
m_VFS = CreateVfs(20*MiB);
|
||||
|
||||
DeleteDirectory(m_TempDir/"_archivecache"); // clean up in case the last run failed
|
||||
@ -55,8 +53,6 @@ CArchiveBuilder::~CArchiveBuilder()
|
||||
m_VFS.reset();
|
||||
|
||||
DeleteDirectory(m_TempDir/"_archivecache");
|
||||
|
||||
tex_codec_unregister_all();
|
||||
}
|
||||
|
||||
void CArchiveBuilder::AddBaseMod(const OsPath& mod)
|
||||
|
@ -682,8 +682,6 @@ void Shutdown(int UNUSED(flags))
|
||||
g_VBMan.Shutdown();
|
||||
TIMER_END(L"shutdown Renderer");
|
||||
|
||||
tex_codec_unregister_all();
|
||||
|
||||
g_Profiler2.ShutdownGPU();
|
||||
|
||||
// Free cursors before shutting down SDL, as they may depend on SDL.
|
||||
@ -936,8 +934,6 @@ void InitGraphics(const CmdLineArgs& args, int flags)
|
||||
|
||||
RunHardwareDetection();
|
||||
|
||||
tex_codec_register_all();
|
||||
|
||||
const int quality = SANE_TEX_QUALITY_DEFAULT; // TODO: set value from config file
|
||||
SetTextureQuality(quality);
|
||||
|
||||
|
@ -134,7 +134,6 @@ void CReplayPlayer::Replay()
|
||||
|
||||
// Need some stuff for terrain movement costs:
|
||||
// (TODO: this ought to be independent of any graphics code)
|
||||
tex_codec_register_all();
|
||||
new CTerrainTextureManager;
|
||||
g_TexMan.LoadTerrainTextures();
|
||||
|
||||
@ -246,7 +245,6 @@ void CReplayPlayer::Replay()
|
||||
|
||||
// Clean up
|
||||
delete &g_TexMan;
|
||||
tex_codec_unregister_all();
|
||||
|
||||
delete &g_Profiler;
|
||||
delete &g_ProfileViewer;
|
||||
|
@ -41,7 +41,6 @@ public:
|
||||
|
||||
// Need some stuff for terrain movement costs:
|
||||
// (TODO: this ought to be independent of any graphics code)
|
||||
tex_codec_register_all();
|
||||
new CTerrainTextureManager;
|
||||
g_TexMan.LoadTerrainTextures();
|
||||
}
|
||||
@ -49,7 +48,6 @@ public:
|
||||
void tearDown()
|
||||
{
|
||||
delete &g_TexMan;
|
||||
tex_codec_unregister_all();
|
||||
|
||||
g_VFS.reset();
|
||||
|
||||
|
@ -638,7 +638,6 @@ public:
|
||||
|
||||
// Need some stuff for terrain movement costs:
|
||||
// (TODO: this ought to be independent of any graphics code)
|
||||
tex_codec_register_all();
|
||||
new CTerrainTextureManager;
|
||||
g_TexMan.LoadTerrainTextures();
|
||||
|
||||
@ -685,7 +684,6 @@ public:
|
||||
|
||||
// Shut down the world
|
||||
delete &g_TexMan;
|
||||
tex_codec_unregister_all();
|
||||
g_VFS.reset();
|
||||
CXeromyces::Terminate();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user