massive cleanup related to internal format. now calculated along with fmt during reload.
more changes pending (split TexData and its settings; make tex.cpp wrap its data in Handle; clean up 'is loaded' checks) This was SVN commit r1988.
This commit is contained in:
parent
a61e31e0a3
commit
3f15b5555c
@ -8,70 +8,180 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
|
|
||||||
static int get_gl_fmt(TexInfo* ti, GLenum* fmt)
|
int tex_filter = GL_LINEAR;
|
||||||
{
|
uint tex_bpp = 32; // 16 or 32
|
||||||
const bool alpha = (ti->flags & TEX_ALPHA) != 0;
|
|
||||||
const bool bgr = (ti->flags & TEX_BGR) != 0;
|
|
||||||
const bool gray = (ti->flags & TEX_GRAY) != 0;
|
|
||||||
|
|
||||||
switch(ti->flags & TEX_DXT)
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// OpenGL helper routines
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static bool fmt_is_s3tc(GLenum fmt)
|
||||||
|
{
|
||||||
|
// specified to be contiguous, but this is safer.
|
||||||
|
switch(fmt)
|
||||||
{
|
{
|
||||||
case 1:
|
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||||
*fmt = alpha? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||||
return 0;
|
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||||
case 3:
|
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||||
*fmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
return true;
|
||||||
return 0;
|
default:
|
||||||
case 5:
|
return false;
|
||||||
*fmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool filter_uses_mipmaps(GLint filter)
|
||||||
|
{
|
||||||
|
switch(filter)
|
||||||
|
{
|
||||||
|
case GL_NEAREST_MIPMAP_NEAREST:
|
||||||
|
case GL_LINEAR_MIPMAP_NEAREST:
|
||||||
|
case GL_NEAREST_MIPMAP_LINEAR:
|
||||||
|
case GL_LINEAR_MIPMAP_LINEAR:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// determine OpenGL texture format, given <bpp> and TexInfo <flags>.
|
||||||
|
// also choose an internal format based on the global <tex_bpp>
|
||||||
|
// performance vs. quality setting.
|
||||||
|
//
|
||||||
|
// rationale: we override the user's previous internal format preference.
|
||||||
|
// this is reasonable: 1) internal format is mostly performance optimization
|
||||||
|
// 2) if it does turn out to be significant, better to reevaluate the
|
||||||
|
// format decision after a reload than keep the user's setting.
|
||||||
|
static int get_gl_fmt(int bpp, int flags, GLenum* fmt, GLenum* int_fmt)
|
||||||
|
{
|
||||||
|
const bool alpha = (flags & TEX_ALPHA) != 0;
|
||||||
|
const bool bgr = (flags & TEX_BGR ) != 0;
|
||||||
|
const bool gray = (flags & TEX_GRAY ) != 0;
|
||||||
|
const int dxt = flags & TEX_DXT;
|
||||||
|
|
||||||
|
// in case we fail
|
||||||
|
*fmt = 0;
|
||||||
|
*int_fmt = 0;
|
||||||
|
|
||||||
|
// S3TC
|
||||||
|
if(dxt != 0)
|
||||||
|
{
|
||||||
|
switch(dxt)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
*fmt = alpha? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
*fmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
*fmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug_warn("get_gl_fmt: invalid DXT value");
|
||||||
|
return ERR_TEX_FMT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: S3TC textures don't need an internal format, since they're
|
||||||
|
// uploaded via glCompressedTexImage2DARB. we'll set it anyway for
|
||||||
|
// consistency.
|
||||||
|
*int_fmt = *fmt;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(ti->bpp)
|
|
||||||
|
// true => 8 bits per component; otherwise, 4
|
||||||
|
const bool high_quality = (tex_bpp == 32);
|
||||||
|
|
||||||
|
switch(bpp)
|
||||||
{
|
{
|
||||||
case 8:
|
case 8:
|
||||||
*fmt = GL_LUMINANCE;
|
*fmt = GL_LUMINANCE;
|
||||||
|
*int_fmt = high_quality? GL_LUMINANCE8 : GL_LUMINANCE4;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
*fmt = GL_LUMINANCE_ALPHA;
|
*fmt = GL_LUMINANCE_ALPHA;
|
||||||
|
*int_fmt = high_quality? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE4_ALPHA4;
|
||||||
return 0;
|
return 0;
|
||||||
case 24:
|
case 24:
|
||||||
if(!alpha)
|
assert(!alpha);
|
||||||
{
|
*fmt = bgr? GL_BGR : GL_RGB;
|
||||||
*fmt = bgr? GL_BGR : GL_RGB;
|
*int_fmt = high_quality? GL_RGB8 : GL_RGB4;
|
||||||
return 0;
|
// note: BGR can't be used as internal format
|
||||||
}
|
return 0;
|
||||||
break;
|
|
||||||
case 32:
|
case 32:
|
||||||
if(alpha)
|
assert(alpha);
|
||||||
{
|
*fmt = bgr? GL_BGRA : GL_RGBA;
|
||||||
*fmt = bgr? GL_BGRA : GL_RGBA;
|
*int_fmt = high_quality? GL_RGBA8 : GL_RGBA4;
|
||||||
return 0;
|
// note: BGR can't be used as internal format
|
||||||
}
|
return 0;
|
||||||
break;
|
default:
|
||||||
|
debug_warn("get_gl_fmt: invalid bpp");
|
||||||
|
return ERR_TEX_FMT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERR_TEX_FMT_INVALID;
|
// unreachable
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// return a token for glTexParameteri that will enable automatic mipmap
|
||||||
|
// generation, or GL_FALSE if the GL implementation doesn't support it.
|
||||||
|
// does not cache the result.
|
||||||
|
//
|
||||||
|
// rationale: we don't assume GL_GENERATE_MIPMAP and GL_GENERATE_MIPMAP_SGIS
|
||||||
|
// have the same values, although this is implied by the spec governing
|
||||||
|
// 'promoted' ARB extensions. checking for both the old extension and
|
||||||
|
// core 1.4 is future-proof.
|
||||||
|
static GLint detect_auto_mipmap_gen()
|
||||||
|
{
|
||||||
|
// OpenGL 1.4 core. we don't assume this is supported by the driver,
|
||||||
|
// since software implementations usually only have 1.1.
|
||||||
|
if(oglHaveVersion("1.4"))
|
||||||
|
return GL_GENERATE_MIPMAP;
|
||||||
|
|
||||||
|
// widespread extension
|
||||||
|
if(oglHaveExtension("GL_SGIS_generate_mipmap"))
|
||||||
|
return GL_GENERATE_MIPMAP_SGIS;
|
||||||
|
|
||||||
|
// neither supported; need to build manually, e.g. with gluBuild2DMipmaps.
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// texture resource implementation
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct Tex
|
struct Tex
|
||||||
{
|
{
|
||||||
TexInfo ti;
|
TexInfo ti;
|
||||||
|
|
||||||
// determined from TexInfo by Tex_reload
|
// allocated by Tex_reload; indicates the texture is currently uploaded.
|
||||||
GLenum fmt;
|
|
||||||
|
|
||||||
// allocated by Tex_reload
|
|
||||||
GLuint id;
|
GLuint id;
|
||||||
|
|
||||||
// set from user param by tex_upload
|
// determined from TexInfo by gl_get_fmt (called from Tex_reload);
|
||||||
GLint filter;
|
// user settings passed to tex_upload will override this until the
|
||||||
|
// next actual reload.
|
||||||
|
GLenum fmt;
|
||||||
GLenum int_fmt;
|
GLenum int_fmt;
|
||||||
|
|
||||||
|
// set to default <tex_filter> by Tex_init; user settings passed to
|
||||||
|
// tex_upload will permanently override this.
|
||||||
|
GLint filter;
|
||||||
|
|
||||||
// flags influencing reload behavior
|
// flags influencing reload behavior
|
||||||
bool is_loaded;
|
bool is_loaded;
|
||||||
|
// either we have the texture in memory (referenced by ti.hm),
|
||||||
|
// or it's already been uploaded to OpenGL => no reload necessary.
|
||||||
|
// needs to be a flag so it can be reset in Tex_dtor.
|
||||||
bool has_been_uploaded;
|
bool has_been_uploaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,8 +189,10 @@ H_TYPE_DEFINE(Tex);
|
|||||||
|
|
||||||
static void Tex_init(Tex* t, va_list args)
|
static void Tex_init(Tex* t, va_list args)
|
||||||
{
|
{
|
||||||
UNUSED(t);
|
|
||||||
UNUSED(args);
|
UNUSED(args);
|
||||||
|
|
||||||
|
// set to default (once)
|
||||||
|
t->filter = tex_filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Tex_dtor(Tex* t)
|
static void Tex_dtor(Tex* t)
|
||||||
@ -88,6 +200,7 @@ static void Tex_dtor(Tex* t)
|
|||||||
tex_free(&t->ti);
|
tex_free(&t->ti);
|
||||||
|
|
||||||
glDeleteTextures(1, &t->id);
|
glDeleteTextures(1, &t->id);
|
||||||
|
t->id = 0;
|
||||||
|
|
||||||
// need to clear this so actual reloads (triggered by h_reload)
|
// need to clear this so actual reloads (triggered by h_reload)
|
||||||
// actually reload.
|
// actually reload.
|
||||||
@ -100,8 +213,12 @@ static int Tex_reload(Tex* t, const char* fn, Handle h)
|
|||||||
if(t->is_loaded)
|
if(t->is_loaded)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CHECK_ERR(tex_load(fn, &t->ti));
|
TexInfo* const ti = &t->ti;
|
||||||
CHECK_ERR(get_gl_fmt(&t->ti, &t->fmt));
|
CHECK_ERR(tex_load(fn, ti));
|
||||||
|
CHECK_ERR(get_gl_fmt(ti->bpp, ti->flags, &t->fmt, &t->int_fmt));
|
||||||
|
// always override previous settings, since format in
|
||||||
|
// texture file may have changed (e.g. 24 -> 32 bpp).
|
||||||
|
|
||||||
t->is_loaded = true;
|
t->is_loaded = true;
|
||||||
|
|
||||||
glGenTextures(1, &t->id);
|
glGenTextures(1, &t->id);
|
||||||
@ -220,98 +337,16 @@ static int tex_validate(const uint line, const Tex* t)
|
|||||||
#define CHECK_TEX(t) CHECK_ERR(tex_validate(__LINE__, t))
|
#define CHECK_TEX(t) CHECK_ERR(tex_validate(__LINE__, t))
|
||||||
|
|
||||||
|
|
||||||
int tex_filter = GL_LINEAR;
|
|
||||||
uint tex_bpp = 32; // 16 or 32
|
|
||||||
|
|
||||||
|
|
||||||
static int choose_upload_param(Tex* t, GLint* _filter, GLenum* _int_fmt)
|
|
||||||
{
|
|
||||||
if(!*_filter)
|
|
||||||
*_filter = tex_filter;
|
|
||||||
|
|
||||||
// internal format already explicitly requested; we're done.
|
|
||||||
if(*_int_fmt != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
GLenum int_fmt = 0;
|
|
||||||
|
|
||||||
// choose a specific, sized internal format for common formats,
|
|
||||||
// based on the global tex_bpp setting (32 or 16 bpp textures).
|
|
||||||
// could just let the driver choose, but this gives the user
|
|
||||||
// control for performance/quality tweaking.
|
|
||||||
//
|
|
||||||
// rare formats (e.g. GL_BGR) not in the switch statements
|
|
||||||
// are handled below.
|
|
||||||
|
|
||||||
// .. high quality, 32 bit textures (8 bits per component)
|
|
||||||
if(tex_bpp == 32)
|
|
||||||
{
|
|
||||||
switch(t->fmt)
|
|
||||||
{
|
|
||||||
case GL_RGBA:
|
|
||||||
int_fmt = GL_RGBA8;
|
|
||||||
break;
|
|
||||||
case GL_RGB:
|
|
||||||
int_fmt = GL_RGB8;
|
|
||||||
break;
|
|
||||||
case GL_LUMINANCE_ALPHA:
|
|
||||||
int_fmt = GL_LUMINANCE8_ALPHA8;
|
|
||||||
break;
|
|
||||||
case GL_ALPHA:
|
|
||||||
int_fmt = GL_ALPHA8;
|
|
||||||
break;
|
|
||||||
case GL_LUMINANCE:
|
|
||||||
int_fmt = GL_LUMINANCE8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// .. low quality, 16 bit textures (4 bits per component)
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch(t->fmt)
|
|
||||||
{
|
|
||||||
case GL_RGBA:
|
|
||||||
int_fmt = GL_RGBA4;
|
|
||||||
break;
|
|
||||||
case GL_RGB:
|
|
||||||
int_fmt = GL_RGB4;
|
|
||||||
break;
|
|
||||||
case GL_LUMINANCE_ALPHA:
|
|
||||||
int_fmt = GL_LUMINANCE4_ALPHA4;
|
|
||||||
break;
|
|
||||||
case GL_ALPHA:
|
|
||||||
int_fmt = GL_ALPHA4;
|
|
||||||
break;
|
|
||||||
case GL_LUMINANCE:
|
|
||||||
int_fmt = GL_LUMINANCE4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fmt wasn't in the list above, so we haven't chosen
|
|
||||||
// the internal format yet, and need to do so now.
|
|
||||||
// set it to # of components in the texture.
|
|
||||||
// note: can't use the texture data's format -
|
|
||||||
// not all can be used as an internal format! (e.g. GL_BGR)
|
|
||||||
if(!int_fmt)
|
|
||||||
int_fmt = t->ti.bpp / 8;
|
|
||||||
|
|
||||||
*_int_fmt = int_fmt;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
|
int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
|
||||||
{
|
{
|
||||||
H_DEREF(ht, Tex, t);
|
H_DEREF(ht, Tex, t);
|
||||||
|
|
||||||
// someone's requesting upload, but has already been uploaded.
|
// someone's requesting upload, but has already been uploaded.
|
||||||
// this happens if a cached texture is "loaded". no work to do.
|
// this happens if a cached texture is "loaded". no work to do.
|
||||||
if(t->id && t->ti.hm <= 0)
|
if(t->id && t->ti.hm <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
CHECK_TEX(t);
|
CHECK_TEX(t); // must come after check above to avoid false alarms
|
||||||
|
|
||||||
const char* fn = h_filename(ht);
|
const char* fn = h_filename(ht);
|
||||||
if(!fn)
|
if(!fn)
|
||||||
@ -320,79 +355,63 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
|
|||||||
debug_warn("tex_upload(Handle): h_filename failed");
|
debug_warn("tex_upload(Handle): h_filename failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: vars already verified by CHECK_TEX.
|
// allow user override of format/settings
|
||||||
GLsizei w = (GLsizei)t->ti.w;
|
if(filter_ovr) t->filter = filter_ovr;
|
||||||
GLsizei h = (GLsizei)t->ti.h;
|
if(int_fmt_ovr) t->int_fmt = int_fmt_ovr;
|
||||||
u32 bpp = t->ti.bpp; // not used directly in gl calls
|
if(fmt_ovr) t->fmt = fmt_ovr;
|
||||||
GLenum fmt = t->fmt;
|
|
||||||
// .. reference: changed by override below and choose_upload_param
|
// convenient local copies. note: have been validated by CHECK_TEX.
|
||||||
GLint& filter = t->filter;
|
GLsizei w = (GLsizei)t->ti.w;
|
||||||
GLenum& int_fmt = t->int_fmt;
|
GLsizei h = (GLsizei)t->ti.h;
|
||||||
|
u32 bpp = t->ti.bpp; // used for S3TC size calc
|
||||||
|
GLenum fmt = t->fmt;
|
||||||
|
GLint filter = t->filter;
|
||||||
|
GLenum int_fmt = t->int_fmt;
|
||||||
void* tex_data = (char*)mem_get_ptr(t->ti.hm) + t->ti.ofs;
|
void* tex_data = (char*)mem_get_ptr(t->ti.hm) + t->ti.ofs;
|
||||||
|
|
||||||
// allow override
|
// does filter call for uploading mipmaps?
|
||||||
if(filter_ovr) filter = filter_ovr;
|
const bool need_mipmaps = filter_uses_mipmaps(filter);
|
||||||
if(int_fmt_ovr) int_fmt = int_fmt_ovr;
|
static GLint auto_mipmap_gen;
|
||||||
if(fmt_ovr) fmt = fmt_ovr;
|
ONCE(auto_mipmap_gen = detect_auto_mipmap_gen());
|
||||||
|
|
||||||
|
|
||||||
CHECK_ERR(tex_bind(ht));
|
CHECK_ERR(tex_bind(ht));
|
||||||
// we know ht is valid (H_DEREF above), but tex_bind can
|
// we know ht is valid (H_DEREF above), but tex_bind can
|
||||||
// fail in debug builds if Tex.id isn't a valid texture name
|
// fail in debug builds if Tex.id isn't a valid texture name
|
||||||
|
|
||||||
CHECK_ERR(choose_upload_param(t, &filter, &int_fmt));
|
|
||||||
|
|
||||||
// set upload params
|
// set upload params
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||||
const GLint mag = (filter == GL_NEAREST)? GL_NEAREST : GL_LINEAR;
|
const GLint mag_filter = (filter == GL_NEAREST)? GL_NEAREST : GL_LINEAR;
|
||||||
// filter allows mipmaps; magnify can only be linear or nearest
|
// magnify can only be linear or nearest
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
|
||||||
|
|
||||||
// does filter call for uploading mipmaps?
|
if(need_mipmaps)
|
||||||
const bool mipmap = (filter == GL_NEAREST_MIPMAP_NEAREST || filter == GL_LINEAR_MIPMAP_NEAREST ||
|
|
||||||
filter == GL_NEAREST_MIPMAP_LINEAR || filter == GL_LINEAR_MIPMAP_LINEAR);
|
|
||||||
|
|
||||||
// check if SGIS_generate_mipmap is available (once)
|
|
||||||
static int sgm_avl = -1;
|
|
||||||
if(sgm_avl == -1)
|
|
||||||
sgm_avl = (int)oglExtAvail("GL_SGIS_generate_mipmap");
|
|
||||||
|
|
||||||
// S3TC compressed
|
|
||||||
if(fmt >= GL_COMPRESSED_RGB_S3TC_DXT1_EXT &&
|
|
||||||
fmt <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
|
|
||||||
{
|
{
|
||||||
const int tex_size = w * h * bpp / 8;
|
if(auto_mipmap_gen != GL_FALSE)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, auto_mipmap_gen, GL_TRUE);
|
||||||
// RC, 020404: added mipmap generation for DDS textures using GL_SGIS_generate_mipmap - works fine
|
// note: also works on S3TC-compressed textures
|
||||||
// on ATI cards, verified by others under NVIDIA
|
}
|
||||||
if(mipmap)
|
|
||||||
{
|
|
||||||
if (sgm_avl)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
||||||
else
|
|
||||||
// ack - no (easy) way of generating mipmaps for compressed textures; switch back
|
|
||||||
// to a linear minification filter
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if(fmt_is_s3tc(fmt))
|
||||||
|
{
|
||||||
|
// auto generation not supported and gluBuild2DMipmaps doesn't
|
||||||
|
// work for precompressed textures => no easy way to generate
|
||||||
|
// mipmaps. revert to a filter that doesn't require them.
|
||||||
|
if(auto_mipmap_gen == GL_FALSE)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
const GLsizei tex_size = w * h * bpp / 8;
|
||||||
glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size, tex_data);
|
glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size, tex_data);
|
||||||
}
|
}
|
||||||
// normal
|
// uncompressed texture
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
// manual mipmap gen via GLU (box filter)
|
// manual mipmap gen via GLU (box filter)
|
||||||
if(mipmap && !sgm_avl)
|
if(need_mipmaps && !auto_mipmap_gen)
|
||||||
gluBuild2DMipmaps(GL_TEXTURE_2D, int_fmt, w, h, fmt, GL_UNSIGNED_BYTE, tex_data);
|
gluBuild2DMipmaps(GL_TEXTURE_2D, int_fmt, w, h, fmt, GL_UNSIGNED_BYTE, tex_data);
|
||||||
// auto mipmap gen, or no mipmap
|
// auto mipmap gen, or no mipmap
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if(mipmap)
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE, tex_data);
|
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE, tex_data);
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_free_h(t->ti.hm);
|
mem_free_h(t->ti.hm);
|
||||||
@ -405,7 +424,6 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int tex_info(Handle ht, int* w, int* h, int* fmt, int* bpp, void** p)
|
int tex_info(Handle ht, int* w, int* h, int* fmt, int* bpp, void** p)
|
||||||
{
|
{
|
||||||
H_DEREF(ht, Tex, t);
|
H_DEREF(ht, Tex, t);
|
||||||
|
Loading…
Reference in New Issue
Block a user