2010-02-08 17:23:39 +01:00
|
|
|
/* Copyright (c) 2010 Wildfire Games
|
2009-04-18 19:00:33 +02:00
|
|
|
*
|
2010-02-08 17:23:39 +01:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
* a copy of this software and associated documentation files (the
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
* the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
* in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
2009-04-18 19:00:33 +02:00
|
|
|
*/
|
|
|
|
|
2009-04-18 19:51:05 +02:00
|
|
|
/*
|
|
|
|
* support routines and interface for texture codecs.
|
2006-04-24 01:14:18 +02:00
|
|
|
*/
|
|
|
|
|
2007-05-07 18:33:24 +02:00
|
|
|
#ifndef INCLUDED_TEX_CODEC
|
|
|
|
#define INCLUDED_TEX_CODEC
|
2006-04-24 01:14:18 +02:00
|
|
|
|
|
|
|
#include "tex.h"
|
2006-05-31 06:01:59 +02:00
|
|
|
#include "tex_internal.h" // for codec's convenience
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* virtual method table for TexCodecs.
|
|
|
|
* rationale: this works in C and also allows storing name and next in vtbl.
|
|
|
|
* 'template method'-style interface to increase code reuse and
|
|
|
|
* simplify writing new codecs.
|
|
|
|
**/
|
2006-04-24 01:14:18 +02:00
|
|
|
struct TexCodecVTbl
|
|
|
|
{
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* decode the file into a Tex structure.
|
|
|
|
*
|
2011-08-17 10:38:53 +02:00
|
|
|
* @param data input data array (non-const, because the texture
|
2006-05-31 06:01:59 +02:00
|
|
|
* may have to be flipped in-place - see "texture orientation").
|
2011-08-17 10:38:53 +02:00
|
|
|
* @param size [bytes] of data, always >= 4
|
|
|
|
* (this is usually enough to compare the header's "magic" field,
|
|
|
|
* and no legitimate file will be smaller)
|
2006-05-31 06:01:59 +02:00
|
|
|
* @param t output texture object
|
2011-05-03 14:38:42 +02:00
|
|
|
* @return Status
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
2011-08-17 10:38:53 +02:00
|
|
|
Status (*decode)(u8* data, size_t size, Tex* RESTRICT t);
|
2006-05-31 06:01:59 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* encode the texture data into the codec's file format (in memory).
|
|
|
|
*
|
|
|
|
* @param t input texture object. note: non-const because encoding may
|
|
|
|
* require a tex_transform.
|
|
|
|
* @param da output data array, allocated by codec.
|
|
|
|
* rationale: some codecs cannot calculate the output size beforehand
|
|
|
|
* (e.g. PNG output via libpng), so the output memory cannot be allocated
|
|
|
|
* by the caller.
|
2011-05-03 14:38:42 +02:00
|
|
|
* @return Status
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
2011-08-17 10:38:53 +02:00
|
|
|
Status (*encode)(Tex* RESTRICT t, DynArray* RESTRICT da);
|
2006-05-31 06:01:59 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* transform the texture's pixel format.
|
|
|
|
*
|
|
|
|
* @param t texture object
|
|
|
|
* @param transforms: OR-ed combination of TEX_* flags that are to
|
|
|
|
* be changed. note: the codec needs only handle situations specific
|
|
|
|
* to its format; generic pixel format transforms are handled by
|
|
|
|
* the caller.
|
|
|
|
**/
|
2011-05-03 14:38:42 +02:00
|
|
|
Status (*transform)(Tex* t, size_t transforms);
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* indicate if the data appears to be an instance of this codec's header,
|
|
|
|
* i.e. can this codec decode it?
|
|
|
|
*
|
|
|
|
* @param file input data; only guaranteed to be 4 bytes!
|
|
|
|
* (this should be enough to examine the header's 'magic' field)
|
|
|
|
* @return bool
|
|
|
|
**/
|
2007-12-20 21:14:21 +01:00
|
|
|
bool (*is_hdr)(const u8* file);
|
2006-05-31 06:01:59 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* is the extension that of a file format supported by this codec?
|
|
|
|
*
|
|
|
|
* rationale: cannot just return the extension string and have
|
|
|
|
* caller compare it (-> smaller code) because a codec's file format
|
|
|
|
* may have several valid extensions (e.g. jpg and jpeg).
|
|
|
|
*
|
2007-12-22 19:15:52 +01:00
|
|
|
* @param extension (including '.')
|
2006-05-31 06:01:59 +02:00
|
|
|
* @return bool
|
|
|
|
**/
|
2011-03-23 14:36:20 +01:00
|
|
|
bool (*is_ext)(const OsPath& extension);
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* return size of the file header supported by this codec.
|
|
|
|
*
|
|
|
|
* @param file the specific header to return length of (taking its
|
|
|
|
* variable-length fields into account). if NULL, return minimum
|
|
|
|
* guaranteed header size, i.e. the header without any
|
|
|
|
* variable-length fields.
|
|
|
|
* @return size [bytes]
|
|
|
|
**/
|
2006-04-24 01:14:18 +02:00
|
|
|
size_t (*hdr_size)(const u8* file);
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* name of codec for debug purposes. typically set via TEX_CODEC_REGISTER.
|
|
|
|
**/
|
2009-11-03 22:46:35 +01:00
|
|
|
const wchar_t* name;
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* intrusive linked-list of codecs: more convenient than fixed-size
|
|
|
|
* static storage.
|
|
|
|
* set by caller; should be initialized to NULL.
|
|
|
|
**/
|
2006-04-24 01:14:18 +02:00
|
|
|
const TexCodecVTbl* next;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
**/
|
2006-04-24 01:14:18 +02:00
|
|
|
#define TEX_CODEC_REGISTER(name)\
|
2010-02-18 01:06:50 +01:00
|
|
|
static TexCodecVTbl UID__ = \
|
2006-05-31 06:01:59 +02:00
|
|
|
{\
|
|
|
|
name##_decode, name##_encode, name##_transform,\
|
|
|
|
name##_is_hdr, name##_is_ext, name##_hdr_size,\
|
2009-11-03 22:46:35 +01:00
|
|
|
WIDEN(#name)\
|
2006-05-31 06:01:59 +02:00
|
|
|
};\
|
2006-06-02 05:56:24 +02:00
|
|
|
/*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. */\
|
2010-02-18 01:06:50 +01:00
|
|
|
void name##_register() { tex_codec_register(&UID__); }
|
2006-04-24 01:14:18 +02:00
|
|
|
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
**/
|
2006-04-24 01:14:18 +02:00
|
|
|
extern int tex_codec_register(TexCodecVTbl* c);
|
|
|
|
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2010-07-29 17:55:41 +02:00
|
|
|
* Find codec that recognizes the desired output file extension.
|
2006-05-31 06:01:59 +02:00
|
|
|
*
|
2010-07-29 17:55:41 +02:00
|
|
|
* @param extension
|
2006-05-31 06:01:59 +02:00
|
|
|
* @param c (out) vtbl of responsible codec
|
2011-05-03 14:38:42 +02:00
|
|
|
* @return Status; ERR::RES_UNKNOWN_FORMAT (without warning, because this is
|
2006-05-31 06:01:59 +02:00
|
|
|
* called by tex_is_known_extension) if no codec indicates they can
|
|
|
|
* handle the given extension.
|
|
|
|
**/
|
2011-05-03 14:38:42 +02:00
|
|
|
extern Status tex_codec_for_filename(const OsPath& extension, const TexCodecVTbl** c);
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* find codec that recognizes the header's magic field.
|
|
|
|
*
|
|
|
|
* @param data typically contents of file, but need only include the
|
|
|
|
* (first 4 bytes of) header.
|
|
|
|
* @param data_size [bytes]
|
|
|
|
* @param c (out) vtbl of responsible codec
|
2011-05-03 14:38:42 +02:00
|
|
|
* @return Status; ERR::RES_UNKNOWN_FORMAT if no codec indicates they can
|
2006-05-31 06:01:59 +02:00
|
|
|
* handle the given format (header).
|
|
|
|
**/
|
2011-05-03 14:38:42 +02:00
|
|
|
extern Status tex_codec_for_header(const u8* data, size_t data_size, const TexCodecVTbl** c);
|
2006-05-31 06:01:59 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* transform the texture's pixel format.
|
|
|
|
* tries each codec's transform method once, or until one indicates success.
|
|
|
|
*
|
|
|
|
* @param t texture object
|
|
|
|
* @param transforms: OR-ed combination of TEX_* flags that are to
|
|
|
|
* be changed.
|
2011-05-03 14:38:42 +02:00
|
|
|
* @return Status
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
2011-05-03 14:38:42 +02:00
|
|
|
extern Status tex_codec_transform(Tex* t, size_t transforms);
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* allocate an array of row pointers that point into the given texture data.
|
|
|
|
* for texture decoders that support output via row pointers (e.g. PNG),
|
|
|
|
* this allows flipping the image vertically (useful when matching bottom-up
|
|
|
|
* textures to a global orientation) directly, which is much more
|
|
|
|
* efficient than transforming later via copying all pixels.
|
|
|
|
*
|
|
|
|
* @param data the texture data into which row pointers will point.
|
|
|
|
* note: we don't allocate it here because this function is
|
|
|
|
* needed for encoding, too (where data is already present).
|
|
|
|
* @param h height [pixels] of texture.
|
|
|
|
* @param pitch size [bytes] of one texture row, i.e. width*bytes_per_pixel.
|
|
|
|
* @param src_flags TexFlags of source texture. used to extract its
|
|
|
|
* orientation.
|
|
|
|
* @param dst_orientation desired orientation of the output data.
|
|
|
|
* can be one of TEX_BOTTOM_UP, TEX_TOP_DOWN, or 0 for the
|
|
|
|
* "global orientation".
|
|
|
|
* depending on src and dst, the row array is flipped if necessary.
|
|
|
|
**/
|
2006-04-24 01:14:18 +02:00
|
|
|
typedef const u8* RowPtr;
|
2011-04-30 14:34:28 +02:00
|
|
|
extern std::vector<RowPtr> tex_codec_alloc_rows(const u8* data, size_t h, size_t pitch, size_t src_flags, size_t dst_orientation);
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* apply transforms and then copy header and image into output buffer.
|
|
|
|
*
|
|
|
|
* @param t input texture object
|
|
|
|
* @param transforms transformations to be applied to pixel format
|
|
|
|
* @param hdr header data
|
|
|
|
* @param hdr_size [bytes]
|
|
|
|
* @param da output data array (will be expanded as necessary)
|
2011-05-03 14:38:42 +02:00
|
|
|
* @return Status
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
2011-05-03 14:38:42 +02:00
|
|
|
extern Status tex_codec_write(Tex* t, size_t transforms, const void* hdr, size_t hdr_size, DynArray* da);
|
2006-04-24 01:14:18 +02:00
|
|
|
|
2007-05-07 18:33:24 +02:00
|
|
|
#endif // #ifndef INCLUDED_TEX_CODEC
|