janwas
1c1200a049
- add translators from errno and GetLastError to LibError - clarified return values of callbacks (they must return INFO_CB_CONTINUE to continue) - this exposed a few bugs in error handling chains (returning incorrect values); also reduced say-nothing instances of return -1. - move CHECK_ERR etc. macros to lib_error This was SVN commit r3229.
321 lines
11 KiB
C
Executable File
321 lines
11 KiB
C
Executable File
// OpenGL texture API
|
|
//
|
|
// Copyright (c) 2003-2005 Jan Wassenberg
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License as
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// General Public License for more details.
|
|
//
|
|
// Contact info:
|
|
// Jan.Wassenberg@stud.uni-karlsruhe.de
|
|
// http://www.stud.uni-karlsruhe.de/~urkt/
|
|
|
|
/*
|
|
|
|
[KEEP IN SYNC WITH WIKI!]
|
|
|
|
Introduction
|
|
------------
|
|
|
|
This module simplifies use of textures in OpenGL. An easy-to-use
|
|
load/upload/bind/free API is provided, which completely replaces
|
|
direct access to OpenGL's texturing calls.
|
|
|
|
It basically wraps tex.cpp's texture info in a resource object
|
|
(see h_mgr.h) that maintains associated GL state and provides for
|
|
reference counting, caching, hotloading and safe access.
|
|
Additionally, the upload step provides for trading quality vs. speed
|
|
and works around older hardware/drivers.
|
|
|
|
|
|
Texture Parameters
|
|
------------------
|
|
|
|
OpenGL textures are conditioned on several parameters including
|
|
filter and wrap mode. These are typically set once when the texture is
|
|
created, but must survive reloads (1). To that end, all state (2) is
|
|
set via ogl_tex_set_* (instead of direct glTexParameter calls) and
|
|
re-applied after a reload.
|
|
|
|
(1) the purpose of hotloading is to permit artists to see their changes
|
|
in-game without having to restart the map. reloads where the
|
|
texture looks different due to changed state are useless.
|
|
|
|
(2) currently only filter and wrap mode. no other glTexParameter
|
|
settings are used ATM; if that changes, add to OglTexState.
|
|
|
|
|
|
Uploading to OpenGL
|
|
-------------------
|
|
|
|
.. deserves some clarification. This entails calling glTexImage2D
|
|
(or its variants for mipmaps/compressed textures) and transfers
|
|
texture parameters and data from system memory to OpenGL
|
|
(and thereby usually video memory).
|
|
|
|
In so doing, choices are made as to the texture's internal representation
|
|
(how it is stored in vmem) - in particular, the bit depth.
|
|
This can trade performance (more/less data to copy) for quality
|
|
(fidelity to original).
|
|
|
|
We provide a mechanism that applies defaults to all uploads;
|
|
this allows a global "quality" setting that can boost performance on
|
|
older graphics cards without requiring anything else to be changed.
|
|
Textures with specific quality needs can override this via
|
|
ogl_tex_set_* or ogl_tex_upload parameters.
|
|
|
|
Finally, provision is made for coping with hardware/drivers lacking support
|
|
for S3TC decompression or mipmap generation: that can be done in software,
|
|
if necessary. This avoids the need for alternate asset formats and
|
|
lowers hardware requirements. While such cards probably won't run
|
|
the app very well (due to their age and lack of other capabilities),
|
|
this does make possible developing/testing on older machines/laptops.
|
|
|
|
|
|
Caching and Texture Instances
|
|
-----------------------------
|
|
|
|
Caching is both an advantage and drawback. When opening the same
|
|
texture twice without previously freeing it, a reference to the
|
|
first instance is returned. Therefore, be advised that concurrent use of the
|
|
same texture but with differing parameters (e.g. upload quality) followed by
|
|
a reload of the first instance will result in using the wrong parameters.
|
|
For background and rationale why this is acceptable, see struct OglTex.
|
|
|
|
|
|
Example Usage
|
|
-------------
|
|
|
|
Note: to keep the examples simple, we leave out error handling by
|
|
ignoring all return values. Each function will still raise a warning
|
|
(assert) if it fails and passing e.g. invalid Handles will only cause
|
|
the next function to fail, but real apps should check and report errors.
|
|
|
|
1) Basic usage: load texture from file.
|
|
|
|
Handle hTexture = ogl_tex_load("filename.dds");
|
|
(void)ogl_tex_upload(hTexture);
|
|
|
|
[when rendering:]
|
|
(void)ogl_tex_bind(hTexture);
|
|
[.. do something with OpenGL that uses the currently bound texture]
|
|
|
|
[at exit:]
|
|
// (done automatically, but this avoids it showing up as a leak)
|
|
(void)ogl_tex_free(hTexture);
|
|
|
|
|
|
2) Advanced usage: wrap existing texture data, override filter,
|
|
specify internal_format and use multitexturing.
|
|
|
|
Tex t;
|
|
const uint flags = 0; // image is plain RGB, default orientation
|
|
void* data = [pre-existing image]
|
|
(void)tex_wrap(w, h, 24, flags, data, &t);
|
|
Handle hCompositeAlphaMap = ogl_tex_wrap(&t, "(alpha map composite)");
|
|
(void)ogl_tex_set_filter(hCompositeAlphaMap, GL_LINEAR);
|
|
(void)ogl_tex_upload(hCompositeAlphaMap, 0, 0, GL_INTENSITY);
|
|
// (your responsibility! tex_wrap attaches a reference but it is
|
|
// removed by ogl_tex_upload.)
|
|
free(data);
|
|
|
|
[when rendering:]
|
|
(void)ogl_tex_bind(hCompositeAlphaMap, 1);
|
|
[.. do something with OpenGL that uses the currently bound texture]
|
|
|
|
[at exit:]
|
|
// (done automatically, but this avoids it showing up as a leak)
|
|
(void)ogl_tex_free(hCompositeAlphaMap);
|
|
|
|
*/
|
|
|
|
#ifndef OGL_TEX_H__
|
|
#define OGL_TEX_H__
|
|
|
|
#include "../handle.h"
|
|
#include "lib/types.h"
|
|
#include "lib/ogl.h"
|
|
#include "tex.h"
|
|
|
|
|
|
//
|
|
// quality mechanism
|
|
//
|
|
|
|
enum OglTexQualityFlags
|
|
{
|
|
// emphatically require full quality for this texture.
|
|
// (q_flags are invalid if this is set together with any other bit)
|
|
// rationale: the value 0 is used to indicate "use default flags" in
|
|
// ogl_tex_upload and ogl_tex_set_defaults, so this is the only
|
|
// way we can say "disregard default and do not reduce anything".
|
|
OGL_TEX_FULL_QUALITY = 0x20,
|
|
|
|
// store the texture at half the normal bit depth
|
|
// (4 bits per pixel component, as opposed to 8).
|
|
// this increases performance on older graphics cards due to
|
|
// decreased size in vmem. it has no effect on
|
|
// compressed textures because they have a fixed internal format.
|
|
OGL_TEX_HALF_BPP = 0x10,
|
|
|
|
// store the texture at half its original resolution.
|
|
// this increases performance on older graphics cards due to
|
|
// decreased size in vmem.
|
|
// this is useful for also reducing quality of compressed textures,
|
|
// which are not affected by OGL_TEX_HALF_BPP.
|
|
// currently only implemented for images that contain mipmaps
|
|
// (otherwise, we'd have to resample, which is slow).
|
|
// note: scaling down to 1/4, 1/8, .. is easily possible without
|
|
// extra work, so we leave some bits free for that.
|
|
OGL_TEX_HALF_RES = 0x01
|
|
};
|
|
|
|
// change default settings - these affect performance vs. quality.
|
|
// may be overridden for individual textures via parameter to
|
|
// ogl_tex_upload or ogl_tex_set_filter, respectively.
|
|
//
|
|
// pass 0 to keep the current setting; defaults and legal values are:
|
|
// - q_flags: OGL_TEX_FULL_QUALITY; combination of OglTexQualityFlags
|
|
// - filter: GL_LINEAR; any valid OpenGL minification filter
|
|
extern void ogl_tex_set_defaults(uint q_flags, GLint filter);
|
|
|
|
|
|
//
|
|
// open/close
|
|
//
|
|
|
|
// load and return a handle to the texture given in <fn>.
|
|
// for a list of supported formats, see tex.h's tex_load.
|
|
extern Handle ogl_tex_load(const char* fn, uint flags = 0);
|
|
|
|
// return Handle to an existing object, if it has been loaded and
|
|
// is still in memory; otherwise, a negative error code.
|
|
extern Handle ogl_tex_find(const char* fn);
|
|
|
|
// make the given Tex object ready for use as an OpenGL texture
|
|
// and return a handle to it. this will be as if its contents
|
|
// had been loaded by ogl_tex_load.
|
|
//
|
|
// we need only add bookkeeping information and "wrap" it in
|
|
// a resource object (accessed via Handle), hence the name.
|
|
//
|
|
// <fn> isn't strictly needed but should describe the texture so that
|
|
// h_filename will return a meaningful comment for debug purposes.
|
|
// note: because we cannot guarantee that callers will pass distinct
|
|
// "filenames", caching is disabled for the created object. this avoids
|
|
// mistakenly reusing previous objects that share the same comment.
|
|
extern Handle ogl_tex_wrap(Tex* t, const char* fn = 0, uint flags = 0);
|
|
|
|
// free all resources associated with the texture and make further
|
|
// use of it impossible. (subject to refcount)
|
|
extern LibError ogl_tex_free(Handle& ht);
|
|
|
|
|
|
//
|
|
// set texture parameters
|
|
//
|
|
|
|
// these must be called before uploading; this simplifies
|
|
// things and avoids calling glTexParameter twice.
|
|
|
|
// override default filter (as set above) for this texture.
|
|
// must be called before uploading (raises a warning if called afterwards).
|
|
// filter is as defined by OpenGL; it is applied for both minification and
|
|
// magnification (for rationale and details, see OglTexState)
|
|
extern LibError ogl_tex_set_filter(Handle ht, GLint filter);
|
|
|
|
// override default wrap mode (GL_REPEAT) for this texture.
|
|
// must be called before uploading (raises a warning if called afterwards).
|
|
// wrap is as defined by OpenGL and applies to both S and T coordinates
|
|
// (rationale: see OglTexState).
|
|
extern LibError ogl_tex_set_wrap(Handle ht, GLint wrap);
|
|
|
|
|
|
//
|
|
// upload
|
|
//
|
|
|
|
enum OglTexOverrides
|
|
{
|
|
OGL_TEX_S3TC,
|
|
OGL_TEX_AUTO_MIPMAP_GEN
|
|
};
|
|
|
|
enum OglTexAllow
|
|
{
|
|
OGL_TEX_DISABLE,
|
|
OGL_TEX_ENABLE
|
|
};
|
|
|
|
// override the default decision and force/disallow use of the
|
|
// given feature. should be called from ah_override_gl_upload_caps.
|
|
extern void ogl_tex_override(OglTexOverrides what, OglTexAllow allow);
|
|
|
|
// upload the texture to OpenGL.
|
|
// if not 0, parameters override the following:
|
|
// fmt_ovr : OpenGL format (e.g. GL_RGB) decided from bpp / Tex flags;
|
|
// q_flags_ovr : global default "quality vs. performance" flags;
|
|
// int_fmt_ovr : internal format (e.g. GL_RGB8) decided from fmt / q_flags.
|
|
//
|
|
// side effects:
|
|
// - enables texturing on TMU 0 and binds the texture to it;
|
|
// - frees the texel data! see ogl_tex_get_data.
|
|
extern LibError ogl_tex_upload(const Handle ht, GLenum fmt_ovr = 0, uint q_flags_ovr = 0, GLint int_fmt_ovr = 0);
|
|
|
|
|
|
//
|
|
// return information about the texture
|
|
//
|
|
|
|
// retrieve texture dimensions and bits per pixel.
|
|
// all params are optional and filled if non-NULL.
|
|
extern LibError ogl_tex_get_size(Handle ht, uint* w, uint* h, uint* bpp);
|
|
|
|
// retrieve Tex.flags and the corresponding OpenGL format.
|
|
// the latter is determined during ogl_tex_upload and is 0 before that.
|
|
// all params are optional and filled if non-NULL.
|
|
extern LibError ogl_tex_get_format(Handle ht, uint* flags, GLenum* fmt);
|
|
|
|
// retrieve pointer to texel data.
|
|
//
|
|
// note: this memory is freed after a successful ogl_tex_upload for
|
|
// this texture. after that, the pointer we retrieve is NULL but
|
|
// the function doesn't fail (negative return value) by design.
|
|
// if you still need to get at the data, add a reference before
|
|
// uploading it or read directly from OpenGL (discouraged).
|
|
extern LibError ogl_tex_get_data(Handle ht, void** p);
|
|
|
|
|
|
//
|
|
// misc
|
|
//
|
|
|
|
// bind the texture to the specified unit [number] in preparation for
|
|
// using it in rendering. if <ht> is 0, texturing is disabled instead.
|
|
//
|
|
// side effects:
|
|
// - changes the active texture unit;
|
|
// - (if return value is 0:) texturing was enabled/disabled on that unit.
|
|
//
|
|
// notes:
|
|
// - assumes multitexturing is available.
|
|
// - not necessary before calling ogl_tex_upload!
|
|
// - on error, the unit's texture state is unchanged; see implementation.
|
|
extern LibError ogl_tex_bind(Handle ht, uint unit = 0);
|
|
|
|
// apply the specified transforms (as in tex_transform) to the image.
|
|
// must be called before uploading (raises a warning if called afterwards).
|
|
extern LibError ogl_tex_transform(Handle ht, uint flags);
|
|
|
|
// change the pixel format to that specified by <new_flags>.
|
|
// (note: this is equivalent to ogl_tex_transform(ht, ht_flags^new_flags).
|
|
extern LibError ogl_tex_transform_to(Handle ht, uint new_flags);
|
|
|
|
#endif // #ifndef OGL_TEX_H__
|