Added new osg::Texture::SubloadCallback, and getNumMipmapLevels() to osg::Texture

and osg::Image.  This additions are design to make texture subloading more
flexible.
This commit is contained in:
Robert Osfield
2002-08-16 13:33:32 +00:00
parent bff72e1077
commit 7dfefaf67f
5 changed files with 138 additions and 75 deletions

View File

@@ -169,6 +169,21 @@ const unsigned int Image::computeRowWidthInBytes(int width,GLenum format,GLenum
return (widthInBits/packingInBits + ((widthInBits%packingInBits)?1:0))*packing;
}
const unsigned int Image::computeNearestPowerOfTwo(unsigned int s,float bias)
{
if ((s & (s-1))!=0)
{
// it isn't so lets find the closest power of two.
// yes, logf and powf are slow, but this code should
// only be called during scene graph initilization,
// if at all, so not critical in the greater scheme.
float p2 = logf((float)s)/logf(2.0f);
float rounded_p2 = floorf(p2+bias);
s = (int)(powf(2.0f,rounded_p2));
}
return s;
}
void Image::setInternalTextureFormat(GLint internalFormat)
{
// won't do any sanity checking right now, leave it to
@@ -397,58 +412,10 @@ void Image::flipVertical(int image)
void Image::ensureValidSizeForTexturing()
{
int new_s = _s;
int new_t = _t;
int new_s = computeNearestPowerOfTwo(_s);
int new_t = computeNearestPowerOfTwo(_t);
// check if _s is a power of 2 already.
if ((_s & (_s-1))!=0)
{
// it isn't so lets find the closest power of two.
// yes, logf and powf are slow, but this code should
// only be called during scene graph initilization,
// if at all, so not critical in the greater scheme.
float p2 = logf((float)_s)/logf(2.0f);
float rounded_p2 = floorf(p2+0.5f);
new_s = (int)(powf(2.0f,rounded_p2));
}
if ((_t & (_t-1))!=0)
{
// it isn't so lets find the closest power of two.
// yes, logf and powf are slow, but this code should
// only be called during scene graph initilization,
// if at all, so not critical in the greater scheme.
float p2 = logf((float)_t)/logf(2.0f);
float rounded_p2 = floorf(p2+0.5f);
new_t = (int)(powf(2.0f,rounded_p2));
}
static GLint max_size=256;
static bool init = true;
if (init)
{
init = false;
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max_size);
notify(INFO) << "GL_MAX_TEXTURE_SIZE "<<max_size<<std::endl;
char *ptr;
if( (ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0)
{
GLint osg_max_size = atoi(ptr);
notify(INFO) << "OSG_MAX_TEXTURE_SIZE "<<osg_max_size<<std::endl;
if (osg_max_size<max_size)
{
max_size = osg_max_size;
}
}
notify(INFO) << "Selected max texture size "<<max_size<<std::endl;
}
//max_size = 64;
static GLint max_size=Texture::getMaxTextureSize();
if (new_s>max_size) new_s = max_size;
if (new_t>max_size) new_t = max_size;
@@ -462,6 +429,13 @@ void Image::ensureValidSizeForTexturing()
}
}
void Image::computeMipMaps()
{
}
///////////////////////////////////////////////////////////////////////////////
Geode* osg::createGeodeForImage(osg::Image* image)
{
@@ -531,3 +505,4 @@ Geode* osg::createGeodeForImage(osg::Image* image,const float s,const float t)
return NULL;
}
}

View File

@@ -33,6 +33,7 @@ Texture::Texture():
_borderColor(0.0, 0.0, 0.0, 0.0),
_textureWidth(0),
_textureHeight(0),
_numMimpmapLevels(0),
_subloadMode(OFF),
_subloadTextureOffsetX(0),
_subloadTextureOffsetY(0),
@@ -65,13 +66,15 @@ Texture::Texture(const Texture& text,const CopyOp& copyop):
_borderColor(text._borderColor),
_textureWidth(text._textureWidth),
_textureHeight(text._textureHeight),
_numMimpmapLevels(text._numMimpmapLevels),
_subloadMode(text._subloadMode),
_subloadTextureOffsetX(text._subloadTextureOffsetX),
_subloadTextureOffsetY(text._subloadTextureOffsetY),
_subloadImageOffsetX(text._subloadImageOffsetX),
_subloadImageOffsetY(text._subloadImageOffsetY),
_subloadImageWidth(text._subloadImageWidth),
_subloadImageHeight(text._subloadImageHeight)
_subloadImageHeight(text._subloadImageHeight),
_subloadCallback(text._subloadCallback)
{}
Texture::~Texture()
@@ -223,7 +226,7 @@ void Texture::apply(State& state) const
const uint contextID = state.getContextID();
// get the globj for the current contextID.
GLuint& handle = getHandle(contextID);
GLuint& handle = getTextureObject(contextID);
if (handle != 0)
{
@@ -254,6 +257,11 @@ void Texture::apply(State& state) const
// update the modified flag to show that the image has been loaded.
modifiedTag = _image->getModifiedTag();
}
else if (_subloadMode == USE_CALLBACK)
{
_subloadCallback->subload(_target,*this,state);
}
}
}
else if (_image.valid() && _image->data())
@@ -455,6 +463,8 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
}
_internalFormatValue = internalFormat;
// an experiment to look at the changes in performance
// when use 16 bit textures rather than 24/32bit textures.
// internalFormat = GL_RGBA4;
@@ -464,10 +474,12 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
(MyCompressedTexImage2DArbProc)getGLExtensionFuncPtr("glCompressedTexImage2DARB");
if (_subloadMode == OFF) {
if( _min_filter == LINEAR || _min_filter == NEAREST )
{
if ( !compressed )
{
_numMimpmapLevels = 1;
glTexImage2D( target, 0, internalFormat,
image->s(), image->t(), 0,
(GLenum)image->getPixelFormat(),
@@ -477,6 +489,7 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
}
else if(glCompressedTexImage2D_ptr)
{
_numMimpmapLevels = 1;
GLint blockSize = ( internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 );
GLint size = ((image->s()+3)/4)*((image->t()+3)/4)*blockSize;
glCompressedTexImage2D_ptr(target, 0, internalFormat,
@@ -491,21 +504,26 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
{
if(!image->isMipmap())
{
_numMimpmapLevels = 1;
gluBuild2DMipmaps( target, internalFormat,
image->s(),image->t(),
(GLenum)image->getPixelFormat(), (GLenum)image->getDataType(),
image->data() );
image->s(),image->t(),
(GLenum)image->getPixelFormat(), (GLenum)image->getDataType(),
image->data() );
}
else
{
size_t no_mipmaps = image->getNumMipmaps();
_numMimpmapLevels = image->getNumMipmapLevels();
int width = image->s();
int height = image->t();
if( !compressed )
{
for( size_t k = 0 ; k < no_mipmaps && (width || height) ;k++)
for( size_t k = 0 ; k < _numMimpmapLevels && (width || height) ;k++)
{
if (width == 0)
@@ -527,7 +545,7 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
{
GLint blockSize = ( internalFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ? 8 : 16 );
GLint size = 0;
for( size_t k = 0 ; k < no_mipmaps && (width || height) ;k++)
for( size_t k = 0 ; k < _numMimpmapLevels && (width || height) ;k++)
{
if (width == 0)
width = 1;
@@ -549,13 +567,23 @@ void Texture::applyTexImage(GLenum target, Image* image, State& state) const
_textureWidth = image->s();
_textureHeight = image->t();
}
else if (_subloadMode == USE_CALLBACK)
{
_subloadCallback->load(target,*this,state);
}
else
{
static bool s_SGIS_GenMipmap = isGLExtensionSupported("GL_SGIS_generate_mipmap");
if (s_SGIS_GenMipmap && (_min_filter != LINEAR && _min_filter != NEAREST)) {
if (s_SGIS_GenMipmap && (_min_filter != LINEAR && _min_filter != NEAREST))
{
_numMimpmapLevels = 1; // will leave this at one, since the mipmap will be created internally by OpenGL.
glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
}
else
{
_numMimpmapLevels = 1;
}
GLsizei width = (_subloadImageWidth>0)?_subloadImageWidth:image->s();
GLsizei height = (_subloadImageHeight>0)?_subloadImageHeight:image->t();
@@ -631,7 +659,7 @@ void Texture::copyTexImage2D(State& state, int x, int y, int width, int height )
const uint contextID = state.getContextID();
// get the globj for the current contextID.
GLuint& handle = getHandle(contextID);
GLuint& handle = getTextureObject(contextID);
if (handle)
{
@@ -687,7 +715,7 @@ void Texture::copyTexSubImage2D(State& state, int xoffset, int yoffset, int x, i
const uint contextID = state.getContextID();
// get the globj for the current contextID.
GLuint& handle = getHandle(contextID);
GLuint& handle = getTextureObject(contextID);
if (handle)
{
@@ -711,3 +739,31 @@ void Texture::copyTexSubImage2D(State& state, int xoffset, int yoffset, int x, i
copyTexImage2D(state,x,y,width,height);
}
}
GLint Texture::getMaxTextureSize()
{
static GLint s_maxTextureSize = 0;
if (s_maxTextureSize == 0)
{
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&s_maxTextureSize);
notify(INFO) << "GL_MAX_TEXTURE_SIZE "<<s_maxTextureSize<<std::endl;
char *ptr;
if( (ptr = getenv("OSG_MAX_TEXTURE_SIZE")) != 0)
{
GLint osg_max_size = atoi(ptr);
notify(INFO) << "OSG_MAX_TEXTURE_SIZE "<<osg_max_size<<std::endl;
if (osg_max_size<s_maxTextureSize)
{
s_maxTextureSize = osg_max_size;
}
}
notify(INFO) << "Selected max texture size "<<s_maxTextureSize<<std::endl;
}
return s_maxTextureSize;
}

View File

@@ -179,7 +179,7 @@ void TextureCubeMap::apply(State& state) const
const uint contextID = state.getContextID();
// get the globj for the current contextID.
GLuint& handle = getHandle(contextID);
GLuint& handle = getTextureObject(contextID);
if (handle != 0)
{
@@ -196,14 +196,13 @@ void TextureCubeMap::apply(State& state) const
glBindTexture( _target, handle );
if (_texParamtersDirty) applyTexParameters(_target,state);
unsigned int rowwidth = 0;
int rowwidth = 0;
for (int n=0; n<6; n++)
{
if ((_subloadMode == AUTO) ||
(_subloadMode == IF_DIRTY && modifiedTag != _images[n]->getModifiedTag()))
{
if (rowwidth != _images[n]->s())
{
rowwidth = _images[n]->s();
@@ -218,6 +217,10 @@ void TextureCubeMap::apply(State& state) const
// update the modified flag to show that the image has been loaded.
modifiedTag += _images[n]->getModifiedTag();
}
else if (_subloadMode == USE_CALLBACK)
{
_subloadCallback->subload(faceTarget[n],*this,state);
}
}
glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
}