1
0
forked from 0ad/0ad

Cleanup tex_codec, fixes #2456, patch by IronNerd.

This was SVN commit r14836.
This commit is contained in:
JoshuaJB 2014-03-13 04:16:20 +00:00
parent a5639631ee
commit ef888367aa
18 changed files with 134 additions and 273 deletions

View File

@ -38,14 +38,10 @@ public:
m_VFS = CreateVfs(20*MiB); 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"", DataDir()/"mods"/"_test.tex", VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(m_VFS->Mount(L"cache/", DataDir()/"_testcache")); TS_ASSERT_OK(m_VFS->Mount(L"cache/", DataDir()/"_testcache"));
tex_codec_register_all();
} }
void tearDown() void tearDown()
{ {
tex_codec_unregister_all();
m_VFS.reset(); m_VFS.reset();
DeleteDirectory(DataDir()/"_testcache"); DeleteDirectory(DataDir()/"_testcache");
} }

View File

@ -41,7 +41,6 @@ public:
TS_ASSERT_OK(m_VFS->Mount(L"cache/", DataDir()/"_testcache")); TS_ASSERT_OK(m_VFS->Mount(L"cache/", DataDir()/"_testcache"));
h_mgr_init(); h_mgr_init();
tex_codec_register_all();
CXeromyces::Startup(); CXeromyces::Startup();
} }
@ -50,7 +49,6 @@ public:
{ {
CXeromyces::Terminate(); CXeromyces::Terminate();
tex_codec_unregister_all();
h_mgr_shutdown(); h_mgr_shutdown();
m_VFS.reset(); m_VFS.reset();

View File

@ -64,74 +64,6 @@ class TestTex : public CxxTest::TestSuite
} }
public: 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 // have mipmaps be created for a test image; check resulting size and pixels
void test_mipmap_create() void test_mipmap_create()
{ {
@ -164,8 +96,6 @@ public:
void test_s3tc_decode() void test_s3tc_decode()
{ {
tex_codec_register_all();
const size_t w = 4, h = 4, bpp = 4; const size_t w = 4, h = 4, bpp = 4;
const size_t size = w*h/2; const size_t size = w*h/2;
shared_ptr<u8> img(new u8[size], ArrayDeleter()); shared_ptr<u8> img(new u8[size], ArrayDeleter());
@ -187,8 +117,5 @@ public:
// compare img // compare img
TS_ASSERT_SAME_DATA(t.get_data(), expected, 48); TS_ASSERT_SAME_DATA(t.get_data(), expected, 48);
// cleanup
tex_codec_unregister_all();
} }
}; };

View File

@ -569,7 +569,7 @@ bool tex_orientations_match(size_t src_flags, size_t dst_orientation)
// but this is open to misuse. // but this is open to misuse.
bool tex_is_known_extension(const VfsPath& pathname) bool tex_is_known_extension(const VfsPath& pathname)
{ {
const TexCodecVTbl* dummy; const ITexCodec* dummy;
// found codec for it => known extension // found codec for it => known extension
const OsPath extension = pathname.Extension(); const OsPath extension = pathname.Extension();
if(tex_codec_for_filename(extension, &dummy) == INFO::OK) 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. // directly into the output buffer and makes for zero-copy IO.
size_t tex_hdr_size(const VfsPath& filename) size_t tex_hdr_size(const VfsPath& filename)
{ {
const TexCodecVTbl* c; const ITexCodec* c;
const OsPath extension = filename.Extension(); const OsPath extension = filename.Extension();
WARN_RETURN_STATUS_IF_ERR(tex_codec_for_filename(extension, &c)); 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) 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)); RETURN_STATUS_IF_ERR(tex_codec_for_header(Data.get(), DataSize, &c));
// make sure the entire header is available // 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; const size_t max_out_size = img_size()*4 + 256*KiB;
RETURN_STATUS_IF_ERR(da_alloc(da, max_out_size)); 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)); WARN_RETURN_STATUS_IF_ERR(tex_codec_for_filename(extension, &c));
// encode into <da> // encode into <da>

View File

@ -367,22 +367,6 @@ struct Tex
extern void tex_set_global_orientation(int orientation); 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 * special value for levels_to_skip: the callback will only be called
* for the base mipmap level (i.e. 100%) * for the base mipmap level (i.e. 100%)

View File

@ -60,13 +60,13 @@ struct BmpHeader
#define BI_RGB 0 // biCompression #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; 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"?). // check header signature (bfType == "BM"?).
// we compare single bytes to be endian-safe. // 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"; 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); const size_t hdr_size = sizeof(BmpHeader);
if(file) if(file)
@ -95,7 +95,7 @@ static size_t bmp_hdr_size(const u8* file)
// requirements: uncompressed, direct colour, bottom up // 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 BmpHeader* hdr = (const BmpHeader*)data;
const long w = (long)read_le32(&hdr->biWidth); 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 hdr_size = sizeof(BmpHeader); // needed for BITMAPFILEHEADER
const size_t img_size = t->img_size(); 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); return tex_codec_write(t, transforms, &hdr, hdr_size, da);
} }
TEX_CODEC_REGISTER(bmp);

View File

@ -33,85 +33,63 @@
#include "lib/allocators/shared_ptr.h" // ArrayDeleter #include "lib/allocators/shared_ptr.h" // ArrayDeleter
#include "tex.h" #include "tex.h"
static const TexCodecVTbl* codecs; // Statically allocate all of the codecs...
TexCodecDds DdsCodec;
// add this vtbl to the codec list. called at NLSO init time by the TexCodecPng PngCodec;
// TEX_CODEC_REGISTER in each codec file. note that call order and therefore TexCodecJpg JpgCodec;
// order in the list is undefined, but since each codec only steps up if it TexCodecTga TgaCodec;
// can handle the given format, this is not a problem. TexCodecPng BmpCodec;
// // Codecs will be searched in this order
// returns int to alloc calling from a macro at file scope. static const ITexCodec *codecs[] = {(ITexCodec *)&DdsCodec, (ITexCodec *)&PngCodec,
int tex_codec_register(TexCodecVTbl* c) (ITexCodec *)&JpgCodec, (ITexCodec *)&TgaCodec, (ITexCodec *)&BmpCodec};
{ static const int codecs_len = sizeof(codecs) / sizeof(ITexCodec*);
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;
}
// find codec that recognizes the desired output file extension, // find codec that recognizes the desired output file extension,
// or return ERR::TEX_UNKNOWN_FORMAT if unknown. // or return ERR::TEX_UNKNOWN_FORMAT if unknown.
// note: does not raise a warning because it is used by // note: does not raise a warning because it is used by
// tex_is_known_extension. // 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 // we found it
if((*c)->is_ext(extension)) if(codecs[i]->is_ext(extension)) {
*c = codecs[i];
return INFO::OK; return INFO::OK;
} }
}
return ERR::TEX_UNKNOWN_FORMAT; // NOWARN return ERR::TEX_UNKNOWN_FORMAT; // NOWARN
} }
// find codec that recognizes the header's magic field // 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 // we guarantee at least 4 bytes for is_hdr to look at
if(file_size < 4) if(file_size < 4)
WARN_RETURN(ERR::TEX_INCOMPLETE_HEADER); WARN_RETURN(ERR::TEX_INCOMPLETE_HEADER);
for(*c = codecs; *c; *c = (*c)->next) for(int i = 0; i < codecs_len; ++i)
{ {
// we found it // we found it
if((*c)->is_hdr(file)) if(codecs[i]->is_hdr(file)) {
*c = codecs[i];
return INFO::OK; return INFO::OK;
} }
}
WARN_RETURN(ERR::TEX_UNKNOWN_FORMAT); 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 tex_codec_transform(Tex* t, size_t transforms)
{ {
Status ret = INFO::TEX_CODEC_CANNOT_HANDLE; Status ret = INFO::TEX_CODEC_CANNOT_HANDLE;
// find codec that understands the data, and transform // 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 // success
if(err == INFO::OK) if(err == INFO::OK)
return INFO::OK; return INFO::OK;
@ -131,17 +109,6 @@ Status tex_codec_transform(Tex* t, size_t transforms)
// helper functions used by codecs // 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. // allocate an array of row pointers that point into the given texture data.
// <file_orientation> indicates whether the file format is top-down or // <file_orientation> indicates whether the file format is top-down or
// bottom-up; the row array is inverted if necessary to match global // bottom-up; the row array is inverted if necessary to match global

View File

@ -36,8 +36,9 @@
* 'template method'-style interface to increase code reuse and * 'template method'-style interface to increase code reuse and
* simplify writing new codecs. * simplify writing new codecs.
**/ **/
struct TexCodecVTbl class ITexCodec
{ {
public:
/** /**
* decode the file into a Tex structure. * decode the file into a Tex structure.
* *
@ -49,7 +50,7 @@ struct TexCodecVTbl
* @param t output texture object * @param t output texture object
* @return Status * @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). * encode the texture data into the codec's file format (in memory).
@ -62,7 +63,7 @@ struct TexCodecVTbl
* by the caller. * by the caller.
* @return Status * @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. * transform the texture's pixel format.
@ -73,7 +74,7 @@ struct TexCodecVTbl
* to its format; generic pixel format transforms are handled by * to its format; generic pixel format transforms are handled by
* the caller. * 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, * 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) * (this should be enough to examine the header's 'magic' field)
* @return bool * @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? * is the extension that of a file format supported by this codec?
@ -95,7 +96,7 @@ struct TexCodecVTbl
* @param extension (including '.') * @param extension (including '.')
* @return bool * @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. * return size of the file header supported by this codec.
@ -106,59 +107,85 @@ struct TexCodecVTbl
* variable-length fields. * variable-length fields.
* @return size [bytes] * @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. * name of codec for debug purposes. typically set via TEX_CODEC_REGISTER.
**/ **/
const wchar_t* name; virtual const wchar_t* get_name() const = 0;
/** virtual ~ITexCodec() {}
* intrusive linked-list of codecs: more convenient than fixed-size
* static storage.
* set by caller; should be initialized to NULL.
**/
const TexCodecVTbl* next;
}; };
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;
};
};
/** class TexCodecJpg:ITexCodec {
* build codec vtbl and register it. the codec will be queried for future public:
* texture load requests. call order is undefined, but since each codec virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
* only steps up if it can handle the given format, this is not a problem. virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
* virtual Status transform(Tex* t, size_t transforms) const;
* @param name identifier of codec (not string!). used to bind 'member' virtual bool is_hdr(const u8* file) const;
* functions prefixed with it to the vtbl, and as the TexCodecVTbl name. virtual bool is_ext(const OsPath& extension) const;
* it should also mirror the default file extension (e.g. dds) - virtual size_t hdr_size(const u8* file) const;
* this is relied upon (but verified) in the self-test. virtual const wchar_t* get_name() const {
* static const wchar_t *name = L"jpg";
* usage: at file scope within the source file containing the codec's methods. return name;
**/ };
#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 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;
};
};
/** class TexCodecTga:ITexCodec {
* add this vtbl to the codec list. called at NLSO init time by the public:
* TEX_CODEC_REGISTER in each codec file. virtual Status decode(u8* data, size_t size, Tex* RESTRICT t) const;
* order in list is unspecified; see TEX_CODEC_REGISTER. virtual Status encode(Tex* RESTRICT t, DynArray* RESTRICT da) const;
* virtual Status transform(Tex* t, size_t transforms) const;
* @param c pointer to vtbl. virtual bool is_hdr(const u8* file) const;
* @return int (allows calling from a macro at file scope; value is not used) virtual bool is_ext(const OsPath& extension) const;
**/ virtual size_t hdr_size(const u8* file) const;
extern int tex_codec_register(TexCodecVTbl* c); 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. * 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 * called by tex_is_known_extension) if no codec indicates they can
* handle the given extension. * 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. * 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 * @return Status; ERR::RES_UNKNOWN_FORMAT if no codec indicates they can
* handle the given format (header). * handle the given format (header).
**/ **/
extern Status tex_codec_for_header(const u8* data, size_t data_size, const TexCodecVTbl** c); extern Status tex_codec_for_header(const u8* data, size_t data_size, const ITexCodec** 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);
/** /**
* transform the texture's pixel format. * transform the texture's pixel format.

View File

@ -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',' '); 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"; 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); 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); 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)); 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 // note: do not return ERR::NOT_SUPPORTED et al. because that would
// break tex_write (which assumes either this, 0 or errors are returned). // 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); 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); 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. // both not DXT (nothing we can do) - bail.
return INFO::TEX_CODEC_CANNOT_HANDLE; return INFO::TEX_CODEC_CANNOT_HANDLE;
} }
TEX_CODEC_REGISTER(dds);

View File

@ -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; 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. // JFIF requires SOI marker at start of stream.
// we compare single bytes to be endian-safe. // 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"; 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 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 // contains the JPEG decompression parameters and pointers to
// working space (allocated as needed by the JPEG library). // 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 // 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 // contains the JPEG compression parameters and pointers to
// working space (allocated as needed by the JPEG library). // 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; return ret;
} }
TEX_CODEC_REGISTER(jpg);

View File

@ -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; 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 // don't use png_sig_cmp, so we don't pull in libpng for
// this check alone (it might not actually be used). // 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"; 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 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); TIMER_ADD_CLIENT(tc_png_decode);
// limitation: palette images aren't supported // 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); TIMER_ACCRUE(tc_png_decode);
@ -257,7 +257,7 @@ TIMER_ACCRUE(tc_png_decode);
// limitation: palette images aren't supported // 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; Status ret = ERR::FAIL;
png_infop info_ptr = 0; png_infop info_ptr = 0;
@ -284,5 +284,3 @@ fail:
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
return ret; return ret;
} }
TEX_CODEC_REGISTER(png);

View File

@ -67,13 +67,13 @@ TgaHeader;
#pragma pack(pop) #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; 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; 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"; 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); size_t hdr_size = sizeof(TgaHeader);
if(file) if(file)
@ -112,7 +112,7 @@ static size_t tga_hdr_size(const u8* file)
// requirements: uncompressed, direct color, bottom up // 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 TgaHeader* hdr = (const TgaHeader*)data;
const u8 type = hdr->img_type; 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; u8 img_desc = 0;
if(t->m_Flags & TEX_TOP_DOWN) 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); return tex_codec_write(t, transforms, &hdr, hdr_size, da);
} }
TEX_CODEC_REGISTER(tga);

View File

@ -44,7 +44,6 @@ public:
// Need some stuff for terrain movement costs: // Need some stuff for terrain movement costs:
// (TODO: this ought to be independent of any graphics code) // (TODO: this ought to be independent of any graphics code)
tex_codec_register_all();
new CTerrainTextureManager; new CTerrainTextureManager;
g_TexMan.LoadTerrainTextures(); g_TexMan.LoadTerrainTextures();
@ -56,7 +55,6 @@ public:
enet_deinitialize(); enet_deinitialize();
delete &g_TexMan; delete &g_TexMan;
tex_codec_unregister_all();
CXeromyces::Terminate(); CXeromyces::Terminate();
g_VFS.reset(); g_VFS.reset();

View File

@ -36,8 +36,6 @@
CArchiveBuilder::CArchiveBuilder(const OsPath& mod, const OsPath& tempdir) : CArchiveBuilder::CArchiveBuilder(const OsPath& mod, const OsPath& tempdir) :
m_TempDir(tempdir) m_TempDir(tempdir)
{ {
tex_codec_register_all();
m_VFS = CreateVfs(20*MiB); m_VFS = CreateVfs(20*MiB);
DeleteDirectory(m_TempDir/"_archivecache"); // clean up in case the last run failed DeleteDirectory(m_TempDir/"_archivecache"); // clean up in case the last run failed
@ -55,8 +53,6 @@ CArchiveBuilder::~CArchiveBuilder()
m_VFS.reset(); m_VFS.reset();
DeleteDirectory(m_TempDir/"_archivecache"); DeleteDirectory(m_TempDir/"_archivecache");
tex_codec_unregister_all();
} }
void CArchiveBuilder::AddBaseMod(const OsPath& mod) void CArchiveBuilder::AddBaseMod(const OsPath& mod)

View File

@ -682,8 +682,6 @@ void Shutdown(int UNUSED(flags))
g_VBMan.Shutdown(); g_VBMan.Shutdown();
TIMER_END(L"shutdown Renderer"); TIMER_END(L"shutdown Renderer");
tex_codec_unregister_all();
g_Profiler2.ShutdownGPU(); g_Profiler2.ShutdownGPU();
// Free cursors before shutting down SDL, as they may depend on SDL. // Free cursors before shutting down SDL, as they may depend on SDL.
@ -936,8 +934,6 @@ void InitGraphics(const CmdLineArgs& args, int flags)
RunHardwareDetection(); RunHardwareDetection();
tex_codec_register_all();
const int quality = SANE_TEX_QUALITY_DEFAULT; // TODO: set value from config file const int quality = SANE_TEX_QUALITY_DEFAULT; // TODO: set value from config file
SetTextureQuality(quality); SetTextureQuality(quality);

View File

@ -134,7 +134,6 @@ void CReplayPlayer::Replay()
// Need some stuff for terrain movement costs: // Need some stuff for terrain movement costs:
// (TODO: this ought to be independent of any graphics code) // (TODO: this ought to be independent of any graphics code)
tex_codec_register_all();
new CTerrainTextureManager; new CTerrainTextureManager;
g_TexMan.LoadTerrainTextures(); g_TexMan.LoadTerrainTextures();
@ -246,7 +245,6 @@ void CReplayPlayer::Replay()
// Clean up // Clean up
delete &g_TexMan; delete &g_TexMan;
tex_codec_unregister_all();
delete &g_Profiler; delete &g_Profiler;
delete &g_ProfileViewer; delete &g_ProfileViewer;

View File

@ -41,7 +41,6 @@ public:
// Need some stuff for terrain movement costs: // Need some stuff for terrain movement costs:
// (TODO: this ought to be independent of any graphics code) // (TODO: this ought to be independent of any graphics code)
tex_codec_register_all();
new CTerrainTextureManager; new CTerrainTextureManager;
g_TexMan.LoadTerrainTextures(); g_TexMan.LoadTerrainTextures();
} }
@ -49,7 +48,6 @@ public:
void tearDown() void tearDown()
{ {
delete &g_TexMan; delete &g_TexMan;
tex_codec_unregister_all();
g_VFS.reset(); g_VFS.reset();

View File

@ -638,7 +638,6 @@ public:
// Need some stuff for terrain movement costs: // Need some stuff for terrain movement costs:
// (TODO: this ought to be independent of any graphics code) // (TODO: this ought to be independent of any graphics code)
tex_codec_register_all();
new CTerrainTextureManager; new CTerrainTextureManager;
g_TexMan.LoadTerrainTextures(); g_TexMan.LoadTerrainTextures();
@ -685,7 +684,6 @@ public:
// Shut down the world // Shut down the world
delete &g_TexMan; delete &g_TexMan;
tex_codec_unregister_all();
g_VFS.reset(); g_VFS.reset();
CXeromyces::Terminate(); CXeromyces::Terminate();
} }