Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tex.h
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * read/write 2d texture files; allows conversion between pixel formats
25  * and automatic orientation correction.
26  */
27 
28 /**
29 
30 Introduction
31 ------------
32 
33 This module allows reading/writing 2d images in various file formats and
34 encapsulates them in Tex objects.
35 It supports converting between pixel formats; this is to an extent done
36 automatically when reading/writing. Provision is also made for flipping
37 all images to a default orientation.
38 
39 
40 Format Conversion
41 -----------------
42 
43 Image file formats have major differences in their native pixel format:
44 some store in BGR order, or have rows arranged bottom-up.
45 We must balance runtime cost/complexity and convenience for the
46 application (not dumping the entire problem on its lap).
47 That means rejecting really obscure formats (e.g. right-to-left pixels),
48 but converting everything else to uncompressed RGB "plain" format
49 except where noted in enum TexFlags (1).
50 
51 Note: conversion is implemented as a pipeline: e.g. "DDS decompress +
52 vertical flip" would be done by decompressing to RGB (DDS codec) and then
53 flipping (generic transform). This is in contrast to all<->all
54 conversion paths: that would be much more complex, if more efficient.
55 
56 Since any kind of preprocessing at runtime is undesirable (the absolute
57 priority is minimizing load time), prefer file formats that are
58 close to the final pixel format.
59 
60 1) one of the exceptions is S3TC compressed textures. glCompressedTexImage2D
61  requires these be passed in their original format; decompressing would be
62  counterproductive. In this and similar cases, TexFlags indicates such
63  deviations from the plain format.
64 
65 
66 Default Orientation
67 -------------------
68 
69 After loading, all images (except DDS, because its orientation is
70 indeterminate) are automatically converted to the global row
71 orientation: top-down or bottom-up, as specified by
72 tex_set_global_orientation. If that isn't called, the default is top-down
73 to match Photoshop's DDS output (since this is meant to be the
74 no-preprocessing-required optimized format).
75 Reasons to change it might be to speed up loading bottom-up
76 BMP or TGA images, or to match OpenGL's convention for convenience;
77 however, be aware of the abovementioned issues with DDS.
78 
79 Rationale: it is not expected that this will happen at the renderer layer
80 (a 'flip all texcoords' flag is too much trouble), so the
81 application would have to do the same anyway. By taking care of it here,
82 we unburden the app and save time, since some codecs (e.g. PNG) can
83 flip for free when loading.
84 
85 
86 Codecs / IO Implementation
87 --------------------------
88 
89 To ease adding support for new formats, they are organized as codecs.
90 The interface aims to minimize code duplication, so it's organized
91 following the principle of "Template Method" - this module both
92 calls into codecs, and provides helper functions that they use.
93 
94 IO is done via VFS, but the codecs are decoupled from this and
95 work with memory buffers. Access to them is endian-safe.
96 
97 When "writing", the image is put into an expandable memory region.
98 This supports external libraries like libpng that do not know the
99 output size beforehand, but avoids the need for a buffer between
100 library and IO layer. Read and write are zero-copy.
101 
102 **/
103 
104 #ifndef INCLUDED_TEX
105 #define INCLUDED_TEX
106 
107 #include "lib/res/handle.h"
108 #include "lib/os_path.h"
109 #include "lib/file/vfs/vfs_path.h"
110 #include "lib/allocators/dynarray.h"
111 
112 
113 namespace ERR
114 {
115  const Status TEX_UNKNOWN_FORMAT = -120100;
116  const Status TEX_INCOMPLETE_HEADER = -120101;
117  const Status TEX_FMT_INVALID = -120102;
120  const Status TEX_INVALID_LAYOUT = -120105;
121  const Status TEX_COMPRESSED = -120106;
122  const Status TEX_INVALID_SIZE = -120107;
123 }
124 
125 namespace WARN
126 {
127  const Status TEX_INVALID_DATA = +120108;
128 }
129 
130 namespace INFO
131 {
133 }
134 
135 
136 /**
137  * flags describing the pixel format. these are to be interpreted as
138  * deviations from "plain" format, i.e. uncompressed RGB.
139  **/
141 {
142  /**
143  * flags & TEX_DXT is a field indicating compression.
144  * if 0, the texture is uncompressed;
145  * otherwise, it holds the S3TC type: 1,3,5 or DXT1A.
146  * not converted by default - glCompressedTexImage2D receives
147  * the compressed data.
148  **/
149  TEX_DXT = 0x7, // mask
150 
151  /**
152  * we need a special value for DXT1a to avoid having to consider
153  * flags & TEX_ALPHA to determine S3TC type.
154  * the value is arbitrary; do not rely on it!
155  **/
156  DXT1A = 7,
157 
158  /**
159  * indicates B and R pixel components are exchanged. depending on
160  * flags & TEX_ALPHA or bpp, this means either BGR or BGRA.
161  * not converted by default - it's an acceptable format for OpenGL.
162  **/
163  TEX_BGR = 0x08,
164 
165  /**
166  * indicates the image contains an alpha channel. this is set for
167  * your convenience - there are many formats containing alpha and
168  * divining this information from them is hard.
169  * (conversion is not applicable here)
170  **/
171  TEX_ALPHA = 0x10,
172 
173  /**
174  * indicates the image is 8bpp greyscale. this is required to
175  * differentiate between alpha-only and intensity formats.
176  * not converted by default - it's an acceptable format for OpenGL.
177  **/
178  TEX_GREY = 0x20,
179 
180  /**
181  * flags & TEX_ORIENTATION is a field indicating orientation,
182  * i.e. in what order the pixel rows are stored.
183  *
184  * tex_load always sets this to the global orientation
185  * (and flips the image accordingly to match).
186  * texture codecs may in intermediate steps during loading set this
187  * to 0 if they don't know which way around they are (e.g. DDS),
188  * or to whatever their file contains.
189  **/
191  TEX_TOP_DOWN = 0x80,
193 
194  /**
195  * indicates the image data includes mipmaps. they are stored from lowest
196  * to highest (1x1), one after the other.
197  * (conversion is not applicable here)
198  **/
199  TEX_MIPMAPS = 0x100,
200 
202 };
203 
204 
205 /**
206  * stores all data describing an image.
207  * we try to minimize size, since this is stored in OglTex resources
208  * (which are big and pushing the h_mgr limit).
209  **/
210 struct Tex
211 {
212  /**
213  * file buffer or image data. note: during the course of transforms
214  * (which may occur when being loaded), this may be replaced with
215  * a new buffer (e.g. if decompressing file contents).
216  **/
217  shared_ptr<u8> data;
218 
219  size_t dataSize;
220 
221  /**
222  * offset to image data in file. this is required since
223  * tex_get_data needs to return the pixels, but data
224  * returns the actual file buffer. zero-copy load and
225  * write-back to file is also made possible.
226  **/
227  size_t ofs;
228 
229  size_t w;
230  size_t h;
231  size_t bpp;
232 
233  /// see TexFlags and "Format Conversion" in docs.
234  size_t flags;
235 };
236 
237 
238 /**
239  * Is the texture object valid and self-consistent?
240  *
241  * @param t
242  * @return Status
243  **/
244 extern Status tex_validate(const Tex* t);
245 
246 
247 /**
248  * Set the orientation to which all loaded images will
249  * automatically be converted (excepting file formats that don't specify
250  * their orientation, i.e. DDS). See "Default Orientation" in docs.
251  * @param orientation Either TEX_BOTTOM_UP or TEX_TOP_DOWN.
252  **/
253 extern void tex_set_global_orientation(int orientation);
254 
255 
256 /**
257  * Manually register codecs. must be called before first use of a
258  * codec (e.g. loading a texture).
259  *
260  * This would normally be taken care of by TEX_CODEC_REGISTER, but
261  * no longer works when building as a static library.
262  * Workaround: hard-code a list of codecs in tex_codec.cpp and
263  * call their registration functions.
264  **/
265 extern void tex_codec_register_all();
266 
267 /**
268  * remove all codecs that have been registered.
269  **/
270 extern void tex_codec_unregister_all();
271 
272 /**
273  * decode an in-memory texture file into texture object.
274  *
275  * FYI, currently BMP, TGA, JPG, JP2, PNG, DDS are supported - but don't
276  * rely on this (not all codecs may be included).
277  *
278  * @param data Input data.
279  * @param data_size Its size [bytes].
280  * @param t Output texture object.
281  * @return Status.
282  **/
283 extern Status tex_decode(const shared_ptr<u8>& data, size_t data_size, Tex* t);
284 
285 /**
286  * encode a texture into a memory buffer in the desired file format.
287  *
288  * @param t Input texture object.
289  * @param extension (including '.').
290  * @param da Output memory array. Allocated here; caller must free it
291  * when no longer needed. Invalid unless function succeeds.
292  * @return Status
293  **/
294 extern Status tex_encode(Tex* t, const OsPath& extension, DynArray* da);
295 
296 /**
297  * store the given image data into a Tex object; this will be as if
298  * it had been loaded via tex_load.
299  *
300  * rationale: support for in-memory images is necessary for
301  * emulation of glCompressedTexImage2D and useful overall.
302  * however, we don't want to provide an alternate interface for each API;
303  * these would have to be changed whenever fields are added to Tex.
304  * instead, provide one entry point for specifying images.
305  * note: since we do not know how <img> was allocated, the caller must free
306  * it themselves (after calling tex_free, which is required regardless of
307  * alloc type).
308  *
309  * we need only add bookkeeping information and "wrap" it in
310  * our Tex struct, hence the name.
311  *
312  * @param w,h Pixel dimensions.
313  * @param bpp Bits per pixel.
314  * @param flags TexFlags.
315  * @param data Img texture data. note: size is calculated from other params.
316  * @param ofs
317  * @param t output texture object.
318  * @return Status
319  **/
320 extern Status tex_wrap(size_t w, size_t h, size_t bpp, size_t flags, const shared_ptr<u8>& data, size_t ofs, Tex* t);
321 
322 /**
323  * free all resources associated with the image and make further
324  * use of it impossible.
325  *
326  * @param t texture object (note: not zeroed afterwards; see impl)
327  * @return Status
328  **/
329 extern void tex_free(Tex* t);
330 
331 
332 //
333 // modify image
334 //
335 
336 /**
337  * Change <t>'s pixel format.
338  *
339  * @param t Input texture object.
340  * @param transforms TexFlags that are to be flipped.
341  * @return Status
342  **/
343 extern Status tex_transform(Tex* t, size_t transforms);
344 
345 /**
346  * Change <t>'s pixel format (2nd version)
347  * (note: this is equivalent to tex_transform(t, t->flags^new_flags).
348  *
349  * @param t Input texture object.
350  * @param new_flags desired new value of TexFlags.
351  * @return Status
352  **/
353 extern Status tex_transform_to(Tex* t, size_t new_flags);
354 
355 
356 //
357 // return image information
358 //
359 
360 /**
361  * rationale: since Tex is a struct, its fields are accessible to callers.
362  * this is more for C compatibility than convenience; the following should
363  * be used instead of direct access to the corresponding fields because
364  * they take care of some dirty work.
365  **/
366 
367 /**
368  * return a pointer to the image data (pixels), taking into account any
369  * header(s) that may come before it.
370  *
371  * @param t input texture object
372  * @return pointer to data returned by mem_get_ptr (holds reference)!
373  **/
374 extern u8* tex_get_data(const Tex* t);
375 
376 /**
377  * return the ARGB value of the 1x1 mipmap level of the texture.
378  *
379  * @param t input texture object
380  * @return ARGB value (or 0 if texture does not have mipmaps)
381  **/
382 extern u32 tex_get_average_colour(const Tex* t);
383 
384 /**
385  * return total byte size of the image pixels. (including mipmaps!)
386  * rationale: this is preferable to calculating manually because it's
387  * less error-prone (e.g. confusing bits_per_pixel with bytes).
388  *
389  * @param t input texture object
390  * @return size [bytes]
391  **/
392 extern size_t tex_img_size(const Tex* t);
393 
394 
395 /**
396  * special value for levels_to_skip: the callback will only be called
397  * for the base mipmap level (i.e. 100%)
398  **/
399 const int TEX_BASE_LEVEL_ONLY = -1;
400 
401 /**
402  * callback function for each mipmap level.
403  *
404  * @param level number; 0 for base level (i.e. 100%), or the first one
405  * in case some were skipped.
406  * @param level_w, level_h pixel dimensions (powers of 2, never 0)
407  * @param level_data the level's texels
408  * @param level_data_size [bytes]
409  * @param cbData passed through from tex_util_foreach_mipmap.
410  **/
411 typedef void (*MipmapCB)(size_t level, size_t level_w, size_t level_h, const u8* RESTRICT level_data, size_t level_data_size, void* RESTRICT cbData);
412 
413 /**
414  * for a series of mipmaps stored from base to highest, call back for
415  * each level.
416  *
417  * @param w,h Pixel dimensions.
418  * @param bpp Bits per pixel.
419  * @param data Series of mipmaps.
420  * @param levels_to_skip Number of levels (counting from base) to skip, or
421  * TEX_BASE_LEVEL_ONLY to only call back for the base image.
422  * Rationale: this avoids needing to special case for images with or
423  * without mipmaps.
424  * @param data_padding Minimum pixel dimensions of mipmap levels.
425  * This is used in S3TC images, where each level is actually stored in
426  * 4x4 blocks. usually 1 to indicate levels are consecutive.
427  * @param cb MipmapCB to call.
428  * @param cbData Extra data to pass to cb.
429  **/
430 extern void tex_util_foreach_mipmap(size_t w, size_t h, size_t bpp, const u8* data, int levels_to_skip, size_t data_padding, MipmapCB cb, void* RESTRICT cbData);
431 
432 
433 //
434 // image writing
435 //
436 
437 /**
438  * Is the file's extension that of a texture format supported by tex_load?
439  *
440  * Rationale: tex_load complains if the given file is of an
441  * unsupported type. this API allows users to preempt that warning
442  * (by checking the filename themselves), and also provides for e.g.
443  * enumerating only images in a file picker.
444  * an alternative might be a flag to suppress warning about invalid files,
445  * but this is open to misuse.
446  *
447  * @param pathname Only the extension (starting with '.') is used. case-insensitive.
448  * @return bool
449  **/
450 extern bool tex_is_known_extension(const VfsPath& pathname);
451 
452 /**
453  * return the minimum header size (i.e. offset to pixel data) of the
454  * file format corresponding to the filename.
455  *
456  * rationale: this can be used to optimize calls to tex_write: when
457  * allocating the buffer that will hold the image, allocate this much
458  * extra and pass the pointer as base+hdr_size. this allows writing the
459  * header directly into the output buffer and makes for zero-copy IO.
460  *
461  * @param filename Filename; only the extension (that after '.') is used.
462  * case-insensitive.
463  * @return size [bytes] or 0 on error (i.e. no codec found).
464  **/
465 extern size_t tex_hdr_size(const VfsPath& filename);
466 
467 // RAII wrapper
468 struct ScopedTex : public Tex
469 {
471  {
472  tex_free(this);
473  }
474 };
475 
476 #endif // INCLUDED_TEX
const Status TEX_INVALID_COLOR_TYPE
Definition: tex.h:118
#define u8
Definition: types.h:39
size_t ofs
offset to image data in file.
Definition: tex.h:227
Definition: tex.h:468
const Status TEX_CODEC_CANNOT_HANDLE
Definition: tex.h:132
const int TEX_BASE_LEVEL_ONLY
special value for levels_to_skip: the callback will only be called for the base mipmap level (i...
Definition: tex.h:399
bool tex_is_known_extension(const VfsPath &pathname)
Is the file&#39;s extension that of a texture format supported by tex_load?
Definition: tex.cpp:570
Status tex_transform_to(Tex *t, size_t new_flags)
Change &lt;t&gt;&#39;s pixel format (2nd version) (note: this is equivalent to tex_transform(t, t-&gt;flags^new_flags).
Definition: tex.cpp:494
const Status TEX_COMPRESSED
Definition: tex.h:121
flags &amp; TEX_DXT is a field indicating compression.
Definition: tex.h:149
mask
Definition: tex.h:199
~ScopedTex()
Definition: tex.h:470
indicates the image contains an alpha channel.
Definition: tex.h:171
provides a memory range that can be expanded but doesn&#39;t waste physical memory or relocate itself...
Definition: dynarray.h:39
const Status TEX_INCOMPLETE_HEADER
Definition: tex.h:116
shared_ptr< u8 > data
file buffer or image data.
Definition: tex.h:217
indicates the image is 8bpp greyscale.
Definition: tex.h:178
size_t tex_hdr_size(const VfsPath &filename)
return the minimum header size (i.e.
Definition: tex.cpp:703
size_t h
Definition: tex.h:230
indicates B and R pixel components are exchanged.
Definition: tex.h:163
u32 tex_get_average_colour(const Tex *t)
return the ARGB value of the 1x1 mipmap level of the texture.
Definition: tex.cpp:641
flags &amp; TEX_ORIENTATION is a field indicating orientation, i.e.
Definition: tex.h:190
Status tex_validate(const Tex *t)
Is the texture object valid and self-consistent?
Definition: tex.cpp:60
const Status TEX_FMT_INVALID
Definition: tex.h:117
size_t bpp
Definition: tex.h:231
Definition: path.h:75
const Status TEX_NOT_8BIT_PRECISION
Definition: tex.h:119
u8 * tex_get_data(const Tex *t)
rationale: since Tex is a struct, its fields are accessible to callers.
Definition: tex.cpp:629
const Status TEX_UNKNOWN_FORMAT
Definition: tex.h:115
i64 Status
Error handling system.
Definition: status.h:171
size_t dataSize
Definition: tex.h:219
stores all data describing an image.
Definition: tex.h:210
void tex_set_global_orientation(int o)
Set the orientation to which all loaded images will automatically be converted (excepting file format...
Definition: tex.cpp:513
we need a special value for DXT1a to avoid having to consider flags &amp; TEX_ALPHA to determine S3TC typ...
Definition: tex.h:156
const Status TEX_INVALID_DATA
Definition: tex.h:127
const char * extension
Definition: mongoose.cpp:1736
void tex_util_foreach_mipmap(size_t w, size_t h, size_t bpp, const u8 *pixels, int levels_to_skip, size_t data_padding, MipmapCB cb, void *RESTRICT cbData)
for a series of mipmaps stored from base to highest, call back for each level.
Definition: tex.cpp:132
#define u32
Definition: types.h:41
const Status TEX_INVALID_LAYOUT
Definition: tex.h:120
size_t w
Definition: tex.h:229
#define RESTRICT
Status tex_wrap(size_t w, size_t h, size_t bpp, size_t flags, const shared_ptr< u8 > &data, size_t ofs, Tex *t)
store the given image data into a Tex object; this will be as if it had been loaded via tex_load...
Definition: tex.cpp:593
void(* MipmapCB)(size_t level, size_t level_w, size_t level_h, const u8 *RESTRICT level_data, size_t level_data_size, void *RESTRICT cbData)
callback function for each mipmap level.
Definition: tex.h:411
const Status TEX_INVALID_SIZE
Definition: tex.h:122
void tex_codec_register_all()
Manually register codecs.
Definition: tex_codec.cpp:134
size_t tex_img_size(const Tex *t)
return total byte size of the image pixels.
Definition: tex.cpp:683
Status tex_transform(Tex *t, size_t transforms)
Change &lt;t&gt;&#39;s pixel format.
Definition: tex.cpp:467
void tex_codec_unregister_all()
remove all codecs that have been registered.
Definition: tex_codec.cpp:56
size_t flags
see TexFlags and &quot;Format Conversion&quot; in docs.
Definition: tex.h:234
Status tex_decode(const shared_ptr< u8 > &data, size_t dataSize, Tex *t)
decode an in-memory texture file into texture object.
Definition: tex.cpp:717
void tex_free(Tex *t)
free all resources associated with the image and make further use of it impossible.
Definition: tex.cpp:610
Status tex_encode(Tex *t, const OsPath &extension, DynArray *da)
encode a texture into a memory buffer in the desired file format.
Definition: tex.cpp:750
TexFlags
flags describing the pixel format.
Definition: tex.h:140