Pyrogenesis  trunk
ogl_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  * wrapper for all OpenGL texturing calls. provides caching, hotloading
25  * and lifetime management.
26  */
27 
28 /*
29 
30 [KEEP IN SYNC WITH WIKI!]
31 
32 Introduction
33 ------------
34 
35 This module simplifies use of textures in OpenGL. An easy-to-use
36 load/upload/bind/free API is provided, which completely replaces
37 direct access to OpenGL's texturing calls.
38 
39 It basically wraps tex.cpp's texture info in a resource object
40 (see h_mgr.h) that maintains associated GL state and provides for
41 reference counting, caching, hotloading and safe access.
42 Additionally, the upload step provides for trading quality vs. speed
43 and works around older hardware/drivers.
44 
45 
46 Texture Parameters
47 ------------------
48 
49 OpenGL textures are conditioned on several parameters including
50 filter and wrap mode. These are typically set once when the texture is
51 created, but must survive reloads (1). To that end, all state (2) is
52 set via ogl_tex_set_* (instead of direct glTexParameter calls) and
53 re-applied after a reload.
54 
55 (1) the purpose of hotloading is to permit artists to see their changes
56  in-game without having to restart the map. reloads where the
57  texture looks different due to changed state are useless.
58 
59 (2) currently only filter and wrap mode. no other glTexParameter
60  settings are used ATM; if that changes, add to OglTexState.
61 
62 
63 Uploading to OpenGL
64 -------------------
65 
66 .. deserves some clarification. This entails calling glTexImage2D
67 (or its variants for mipmaps/compressed textures) and transfers
68 texture parameters and data from system memory to OpenGL
69 (and thereby usually video memory).
70 
71 In so doing, choices are made as to the texture's internal representation
72 (how it is stored in vmem) - in particular, the bit depth.
73 This can trade performance (more/less data to copy) for quality
74 (fidelity to original).
75 
76 We provide a mechanism that applies defaults to all uploads;
77 this allows a global "quality" setting that can boost performance on
78 older graphics cards without requiring anything else to be changed.
79 Textures with specific quality needs can override this via
80 ogl_tex_set_* or ogl_tex_upload parameters.
81 
82 Finally, provision is made for coping with hardware/drivers lacking support
83 for S3TC decompression or mipmap generation: that can be done in software,
84 if necessary. This avoids the need for alternate asset formats and
85 lowers hardware requirements. While such cards probably won't run
86 the app very well (due to their age and lack of other capabilities),
87 this does make possible developing/testing on older machines/laptops.
88 
89 
90 Caching and Texture Instances
91 -----------------------------
92 
93 Caching is both an advantage and drawback. When opening the same
94 texture twice without previously freeing it, a reference to the
95 first instance is returned. Therefore, be advised that concurrent use of the
96 same texture but with differing parameters (e.g. upload quality) followed by
97 a reload of the first instance will result in using the wrong parameters.
98 For background and rationale why this is acceptable, see struct OglTex.
99 
100 
101 Example Usage
102 -------------
103 
104 Note: to keep the examples simple, we leave out error handling by
105 ignoring all return values. Each function will still raise a warning
106 (assert) if it fails and passing e.g. invalid Handles will only cause
107 the next function to fail, but real apps should check and report errors.
108 
109 1) Basic usage: load texture from file.
110 
111  Handle hTexture = ogl_tex_load("filename.dds");
112  (void)ogl_tex_upload(hTexture);
113 
114  [when rendering:]
115  (void)ogl_tex_bind(hTexture);
116  [.. do something with OpenGL that uses the currently bound texture]
117 
118  [at exit:]
119  * (done automatically, but this avoids it showing up as a leak)
120  (void)ogl_tex_free(hTexture);
121 
122 
123 2) Advanced usage: wrap existing texture data, override filter,
124  specify internal_format and use multitexturing.
125 
126  Tex t;
127  const size_t flags = 0; * image is plain RGB, default orientation
128  void* data = [pre-existing image]
129  (void)tex_wrap(w, h, 24, flags, data, &t);
130  Handle hCompositeAlphaMap = ogl_tex_wrap(&t, "(alpha map composite)");
131  (void)ogl_tex_set_filter(hCompositeAlphaMap, GL_LINEAR);
132  (void)ogl_tex_upload(hCompositeAlphaMap, 0, 0, GL_INTENSITY);
133  * (your responsibility! tex_wrap attaches a reference but it is
134  * removed by ogl_tex_upload.)
135  free(data);
136 
137  [when rendering:]
138  (void)ogl_tex_bind(hCompositeAlphaMap, 1);
139  [.. do something with OpenGL that uses the currently bound texture]
140 
141  [at exit:]
142  * (done automatically, but this avoids it showing up as a leak)
143  (void)ogl_tex_free(hCompositeAlphaMap);
144 
145 */
146 
147 #ifndef INCLUDED_OGL_TEX
148 #define INCLUDED_OGL_TEX
149 
150 #include "lib/res/handle.h"
151 #include "lib/file/vfs/vfs.h"
152 #include "lib/ogl.h"
153 #include "lib/tex/tex.h"
154 
155 
156 //
157 // quality mechanism
158 //
159 
160 /**
161 * Quality flags for texture uploads.
162 * Specify any of them to override certain aspects of the default.
163 */
165 {
166  /**
167  * emphatically require full quality for this texture.
168  * (q_flags are invalid if this is set together with any other bit)
169  * rationale: the value 0 is used to indicate "use default flags" in
170  * ogl_tex_upload and ogl_tex_set_defaults, so this is the only
171  * way we can say "disregard default and do not reduce anything".
172  */
174 
175  /**
176  * store the texture at half the normal bit depth
177  * (4 bits per pixel component, as opposed to 8).
178  * this increases performance on older graphics cards due to
179  * decreased size in vmem. it has no effect on
180  * compressed textures because they have a fixed internal format.
181  */
183 
184  /**
185  * store the texture at half its original resolution.
186  * this increases performance on older graphics cards due to
187  * decreased size in vmem.
188  * this is useful for also reducing quality of compressed textures,
189  * which are not affected by OGL_TEX_HALF_BPP.
190  * currently only implemented for images that contain mipmaps
191  * (otherwise, we'd have to resample, which is slow).
192  * note: scaling down to 1/4, 1/8, .. is easily possible without
193  * extra work, so we leave some bits free for that.
194  */
196 };
197 
198 /**
199 * Change default settings - these affect performance vs. quality.
200 * May be overridden for individual textures via parameter to
201 * ogl_tex_upload or ogl_tex_set_filter, respectively.
202 *
203 * @param q_flags quality flags. Pass 0 to keep the current setting
204 * (initially OGL_TEX_FULL_QUALITY), or any combination of
205 * OglTexQualityFlags.
206 * @param filter mag/minification filter. Pass 0 to keep the current setting
207 * (initially GL_LINEAR), or any valid OpenGL minification filter.
208 */
209 extern void ogl_tex_set_defaults(int q_flags, GLint filter);
210 
211 
212 //
213 // open/close
214 //
215 
216 /**
217 * Load and return a handle to the texture.
218 *
219 * @param vfs
220 * @param pathname
221 * @param flags h_alloc flags.
222 * @return Handle to texture or negative Status
223 * for a list of supported formats, see tex.h's tex_load.
224 */
225 extern Handle ogl_tex_load(const PIVFS& vfs, const VfsPath& pathname, size_t flags = 0);
226 
227 /**
228 * Find and return an existing texture object, if it has already been
229 * loaded and is still in memory.
230 *
231 * @param pathname fn VFS filename of texture.
232 * @return Handle to texture or negative Status
233 */
234 extern Handle ogl_tex_find(const VfsPath& pathname);
235 
236 /**
237 * Make the Tex object ready for use as an OpenGL texture
238 * and return a handle to it. This will be as if its contents
239 * had been loaded by ogl_tex_load.
240 *
241 * @param t Texture object.
242 * @param vfs
243 * @param pathname filename or description of texture. not strictly needed,
244 * but would allow h_filename to return meaningful info for
245 * purposes of debugging.
246 * @param flags
247 * @return Handle to texture or negative Status
248 *
249 * note: because we cannot guarantee that callers will pass distinct
250 * "filenames", caching is disabled for the created object. this avoids
251 * mistakenly reusing previous objects that share the same comment.
252 *
253 * we need only add bookkeeping information and "wrap" it in
254 * a resource object (accessed via Handle), hence the name.
255 */
256 extern Handle ogl_tex_wrap(Tex* t, const PIVFS& vfs, const VfsPath& pathname, size_t flags = 0);
257 
258 /**
259 * Release this texture reference. When the count reaches zero, all of
260 * its associated resources are freed and further use made impossible.
261 *
262 * @param ht Texture handle.
263 * @return Status
264 */
265 extern Status ogl_tex_free(Handle& ht);
266 
267 
268 //
269 // set texture parameters
270 //
271 
272 // these must be called before uploading; this simplifies
273 // things and avoids calling glTexParameter twice.
274 
275 /**
276 * Override default filter (see {@link #ogl_tex_set_defaults}) for
277 * this texture.
278 *
279 * @param ht Texture handle
280 * @param filter OpenGL minification and magnification filter
281 * (rationale: see {@link OglTexState})
282 * @return Status
283 *
284 * Must be called before uploading (raises a warning if called afterwards).
285 */
286 extern Status ogl_tex_set_filter(Handle ht, GLint filter);
287 
288 /**
289 * Override default wrap mode (GL_REPEAT) for this texture.
290 *
291 * @param ht Texture handle
292 * @param wrap_s OpenGL wrap mode for S coordinates
293 * @param wrap_t OpenGL wrap mode for T coordinates
294 * @return Status
295 *
296 * Must be called before uploading (raises a warning if called afterwards).
297 */
298 extern Status ogl_tex_set_wrap(Handle ht, GLint wrap_s, GLint wrap_t);
299 
300 /**
301 * Override default maximum anisotropic filtering for this texture.
302 *
303 * @param ht Texture handle
304 * @param anisotropy Anisotropy value (must not be less than 1.0; should
305 * usually be a power of two)
306 * @return Status
307 *
308 * Must be called before uploading (raises a warning if called afterwards).
309 */
310 extern Status ogl_tex_set_anisotropy(Handle ht, GLfloat anisotropy);
311 
312 
313 //
314 // upload
315 //
316 
318 {
322 };
323 
325 {
328 };
329 
330 /**
331 * Override the default decision and force/disallow use of the
332 * given feature. Typically called from ah_override_gl_upload_caps.
333 *
334 * @param what Feature to influence.
335 * @param allow Disable/enable flag.
336 */
337 extern void ogl_tex_override(OglTexOverrides what, OglTexAllow allow);
338 
339 /**
340 * Upload texture to OpenGL.
341 *
342 * @param ht Texture handle
343 * @param fmt_ovr optional override for OpenGL format (e.g. GL_RGB),
344 * which is decided from bpp / Tex flags
345 * @param q_flags_ovr optional override for global default
346 * OglTexQualityFlags
347 * @param int_fmt_ovr optional override for OpenGL internal format
348 * (e.g. GL_RGB8), which is decided from fmt / q_flags.
349 * @return Status.
350 *
351 * Side Effects:
352 * - enables texturing on TMU 0 and binds the texture to it;
353 * - frees the texel data! see ogl_tex_get_data.
354 */
355 extern Status ogl_tex_upload(const Handle ht, GLenum fmt_ovr = 0, int q_flags_ovr = 0, GLint int_fmt_ovr = 0);
356 
357 
358 //
359 // return information about the texture
360 //
361 
362 /**
363 * Retrieve dimensions and bit depth of the texture.
364 *
365 * @param ht Texture handle
366 * @param w optional; will be filled with width
367 * @param h optional; will be filled with height
368 * @param bpp optional; will be filled with bits per pixel
369 * @return Status
370 */
371 extern Status ogl_tex_get_size(Handle ht, size_t* w, size_t* h, size_t* bpp);
372 
373 /**
374 * Retrieve pixel format of the texture.
375 *
376 * @param ht Texture handle
377 * @param flags optional; will be filled with TexFlags
378 * @param fmt optional; will be filled with GL format
379 * (it is determined during ogl_tex_upload and 0 before then)
380 * @return Status
381 */
382 extern Status ogl_tex_get_format(Handle ht, size_t* flags, GLenum* fmt);
383 
384 /**
385 * Retrieve pixel data of the texture.
386 *
387 * @param ht Texture handle
388 * @param p will be filled with pointer to texels.
389 * @return Status
390 *
391 * Note: this memory is freed after a successful ogl_tex_upload for
392 * this texture. After that, the pointer we retrieve is NULL but
393 * the function doesn't fail (negative return value) by design.
394 * If you still need to get at the data, add a reference before
395 * uploading it or read directly from OpenGL (discouraged).
396 */
397 extern Status ogl_tex_get_data(Handle ht, u8** p);
398 
399 /**
400 * Retrieve number of bytes uploaded for the texture, including mipmaps.
401 * size will be 0 if the texture has not been uploaded yet.
402 *
403 * @param ht Texture handle
404 * @param size Will be filled with size in bytes
405 * @return Status
406 */
407 extern Status ogl_tex_get_uploaded_size(Handle ht, size_t* size);
408 
409 /**
410  * Retrieve ARGB value of 1x1 mipmap level of the texture,
411  * i.e. the average color of the whole texture.
412  *
413  * @param ht Texture handle
414  * @param p will be filled with ARGB value (or 0 if texture does not have mipmaps)
415  * @return Status
416  *
417  * Must be called before uploading (raises a warning if called afterwards).
418  */
420 
421 
422 //
423 // misc
424 //
425 
426 /**
427 * Bind texture to the specified unit in preparation for using it in
428 * rendering.
429 *
430 * @param ht Texture handle. If 0, texturing is disabled on this unit.
431 * @param unit Texture Mapping Unit number, typically 0 for the first.
432 * @return Status
433 *
434 * Side Effects:
435 * - changes the active texture unit;
436 * - (if successful) texturing was enabled/disabled on that unit.
437 *
438 * Notes:
439 * - assumes multitexturing is available.
440 * - not necessary before calling ogl_tex_upload!
441 * - on error, the unit's texture state is unchanged; see implementation.
442 */
443 extern Status ogl_tex_bind(Handle ht, size_t unit = 0);
444 
445 /**
446 * Return the GL handle of the loaded texture in *id, or 0 on failure.
447 */
448 extern Status ogl_tex_get_texture_id(Handle ht, GLuint* id);
449 
450 /**
451 * (partially) Transform pixel format of the texture.
452 *
453 * @param ht Texture handle.
454 * @param flags the TexFlags that are to be @em changed.
455 * @return Status
456 * @see tex_transform
457 *
458 * Must be called before uploading (raises a warning if called afterwards).
459 */
460 extern Status ogl_tex_transform(Handle ht, size_t flags);
461 
462 /**
463 * Transform pixel format of the texture.
464 *
465 * @param ht Texture handle.
466 * @param new_flags Flags desired new TexFlags indicating pixel format.
467 * @return Status
468 * @see tex_transform
469 *
470 * Must be called before uploading (raises a warning if called afterwards).
471 *
472 * Note: this is equivalent to ogl_tex_transform(ht, ht_flags^new_flags).
473 */
474 extern Status ogl_tex_transform_to(Handle ht, size_t new_flags);
475 
476 /**
477  * Return whether native S3TC texture compression support is available.
478  * If not, textures will be decompressed automatically, hurting performance.
479  *
480  * @return true if native S3TC supported.
481  *
482  * ogl_tex_upload must be called at least once before this.
483  */
484 extern bool ogl_tex_has_s3tc();
485 
486 /**
487  * Return whether anisotropic filtering support is available.
488  * (The anisotropy might still be disabled or overridden by the driver
489  * configuration.)
490  *
491  * @return true if anisotropic filtering supported.
492  *
493  * ogl_tex_upload must be called at least once before this.
494  */
495 extern bool ogl_tex_has_anisotropy();
496 
497 #endif // #ifndef INCLUDED_OGL_TEX
Handle ogl_tex_wrap(Tex *t, const PIVFS &vfs, const VfsPath &pathname, size_t flags=0)
Make the Tex object ready for use as an OpenGL texture and return a handle to it. ...
Definition: ogl_tex.cpp:573
Definition: ogl_tex.h:327
bool ogl_tex_has_s3tc()
Return whether native S3TC texture compression support is available.
Definition: ogl_tex.cpp:1129
Status ogl_tex_get_average_color(Handle ht, u32 *p)
Retrieve ARGB value of 1x1 mipmap level of the texture, i.e.
Definition: ogl_tex.cpp:1043
Handle ogl_tex_load(const PIVFS &vfs, const VfsPath &pathname, size_t flags=0)
Load and return a handle to the texture.
Definition: ogl_tex.cpp:545
Definition: ogl_tex.h:321
Status ogl_tex_get_format(Handle ht, size_t *flags, GLenum *fmt)
Retrieve pixel format of the texture.
Definition: ogl_tex.cpp:1004
Status ogl_tex_bind(Handle ht, size_t unit=0)
Bind texture to the specified unit in preparation for using it in rendering.
Definition: ogl_tex.cpp:1067
shared_ptr< IVFS > PIVFS
Definition: vfs.h:226
Handle ogl_tex_find(const VfsPath &pathname)
Find and return an existing texture object, if it has already been loaded and is still in memory...
Definition: ogl_tex.cpp:554
uint8_t u8
Definition: types.h:37
uint32_t u32
Definition: types.h:39
Definition: ogl_tex.h:320
Status ogl_tex_transform_to(Handle ht, size_t new_flags)
Transform pixel format of the texture.
Definition: ogl_tex.cpp:1120
Status ogl_tex_set_wrap(Handle ht, GLint wrap_s, GLint wrap_t)
Override default wrap mode (GL_REPEAT) for this texture.
Definition: ogl_tex.cpp:660
Definition: path.h:77
Status ogl_tex_set_anisotropy(Handle ht, GLfloat anisotropy)
Override default maximum anisotropic filtering for this texture.
Definition: ogl_tex.cpp:682
Status ogl_tex_get_texture_id(Handle ht, GLuint *id)
Return the GL handle of the loaded texture in *id, or 0 on failure.
Definition: ogl_tex.cpp:1100
emphatically require full quality for this texture.
Definition: ogl_tex.h:173
i64 Status
Error handling system.
Definition: status.h:171
i64 Handle
`handle&#39; representing a reference to a resource (sound, texture, etc.)
Definition: handle.h:41
stores all data describing an image.
Definition: tex.h:209
Status ogl_tex_upload(const Handle ht, GLenum fmt_ovr=0, int q_flags_ovr=0, GLint int_fmt_ovr=0)
Upload texture to OpenGL.
Definition: ogl_tex.cpp:918
Definition: ogl_tex.h:319
store the texture at half its original resolution.
Definition: ogl_tex.h:195
OglTexOverrides
Definition: ogl_tex.h:317
OglTexAllow
Definition: ogl_tex.h:324
Status ogl_tex_free(Handle &ht)
Release this texture reference.
Definition: ogl_tex.cpp:589
void ogl_tex_override(OglTexOverrides what, OglTexAllow allow)
Override the default decision and force/disallow use of the given feature.
Definition: ogl_tex.cpp:714
store the texture at half the normal bit depth (4 bits per pixel component, as opposed to 8)...
Definition: ogl_tex.h:182
bool ogl_tex_has_anisotropy()
Return whether anisotropic filtering support is available.
Definition: ogl_tex.cpp:1138
void ogl_tex_set_defaults(int q_flags, GLint filter)
Change default settings - these affect performance vs.
Definition: ogl_tex.cpp:206
OglTexQualityFlags
Quality flags for texture uploads.
Definition: ogl_tex.h:164
Definition: ogl_tex.h:326
Definition: format.h:119
Status ogl_tex_transform(Handle ht, size_t flags)
(partially) Transform pixel format of the texture.
Definition: ogl_tex.cpp:1110
Definition: vfs_util.cpp:39
Status ogl_tex_get_size(Handle ht, size_t *w, size_t *h, size_t *bpp)
Retrieve dimensions and bit depth of the texture.
Definition: ogl_tex.cpp:987
Status ogl_tex_get_data(Handle ht, u8 **p)
Retrieve pixel data of the texture.
Definition: ogl_tex.cpp:1026
Status ogl_tex_set_filter(Handle ht, GLint filter)
Override default filter (see ogl_tex_set_defaults) for this texture.
Definition: ogl_tex.cpp:641
Status ogl_tex_get_uploaded_size(Handle ht, size_t *size)
Retrieve number of bytes uploaded for the texture, including mipmaps.
Definition: ogl_tex.cpp:1034