From Art Trevs, "Features of the patch are:

- Implementation of integer textures as in EXT_texture_integer

- setBorderColor(Vec4) changed to setBorderColor(Vec4d) to pass double values
as border color. (Probably we have to provide an overloading function to
still support Vec4f ?)

- new method Texture::getInternalFormatType() added. Gives information if the
internal format normalized, float, signed integer or unsigned integer. Can
help people to write better code ;-)

"

Futher changes to this submission by Robert Osfield, changed the dirty mipmap
flag into a buffer_value<> vector to ensure safe handling of multiple contexts.
This commit is contained in:
Robert Osfield
2007-09-11 12:04:58 +00:00
parent 98763cc4c5
commit 5e83ae4821
22 changed files with 807 additions and 48 deletions

View File

@@ -170,6 +170,51 @@ GLenum Image::computePixelFormat(GLenum format)
case(GL_RGBA32F_ARB):
case(GL_RGBA16F_ARB):
return GL_RGBA;
case(GL_ALPHA8I_EXT):
case(GL_ALPHA16I_EXT):
case(GL_ALPHA32I_EXT):
case(GL_ALPHA8UI_EXT):
case(GL_ALPHA16UI_EXT):
case(GL_ALPHA32UI_EXT):
return GL_ALPHA_INTEGER_EXT;
case(GL_LUMINANCE8I_EXT):
case(GL_LUMINANCE16I_EXT):
case(GL_LUMINANCE32I_EXT):
case(GL_LUMINANCE8UI_EXT):
case(GL_LUMINANCE16UI_EXT):
case(GL_LUMINANCE32UI_EXT):
return GL_LUMINANCE_INTEGER_EXT;
case(GL_INTENSITY8I_EXT):
case(GL_INTENSITY16I_EXT):
case(GL_INTENSITY32I_EXT):
case(GL_INTENSITY8UI_EXT):
case(GL_INTENSITY16UI_EXT):
case(GL_INTENSITY32UI_EXT):
notify(WARN)<<"Image::computePixelFormat("<<std::hex<<format<<std::dec<<") intensity pixel format is not correctly specified, so assume GL_LUMINANCE_INTEGER."<<std::endl;
return GL_LUMINANCE_INTEGER_EXT;
case(GL_LUMINANCE_ALPHA8I_EXT):
case(GL_LUMINANCE_ALPHA16I_EXT):
case(GL_LUMINANCE_ALPHA32I_EXT):
case(GL_LUMINANCE_ALPHA8UI_EXT):
case(GL_LUMINANCE_ALPHA16UI_EXT):
case(GL_LUMINANCE_ALPHA32UI_EXT):
return GL_LUMINANCE_ALPHA_INTEGER_EXT;;
case(GL_RGB32I_EXT):
case(GL_RGB16I_EXT):
case(GL_RGB8I_EXT):
case(GL_RGB32UI_EXT):
case(GL_RGB16UI_EXT):
case(GL_RGB8UI_EXT):
return GL_RGB_INTEGER_EXT;
case(GL_RGBA32I_EXT):
case(GL_RGBA16I_EXT):
case(GL_RGBA8I_EXT):
case(GL_RGBA32UI_EXT):
case(GL_RGBA16UI_EXT):
case(GL_RGBA8UI_EXT):
return GL_RGBA_INTEGER_EXT;;
default:
return format;
}
@@ -190,10 +235,22 @@ unsigned int Image::computeNumComponents(GLenum pixelFormat)
case(GL_GREEN): return 1;
case(GL_BLUE): return 1;
case(GL_ALPHA): return 1;
case(GL_ALPHA8I_EXT): return 1;
case(GL_ALPHA8UI_EXT): return 1;
case(GL_ALPHA16I_EXT): return 1;
case(GL_ALPHA16UI_EXT): return 1;
case(GL_ALPHA32I_EXT): return 1;
case(GL_ALPHA32UI_EXT): return 1;
case(GL_ALPHA16F_ARB): return 1;
case(GL_ALPHA32F_ARB): return 1;
case(GL_RGB): return 3;
case(GL_BGR): return 3;
case(GL_RGB8I_EXT): return 3;
case(GL_RGB8UI_EXT): return 3;
case(GL_RGB16I_EXT): return 3;
case(GL_RGB16UI_EXT): return 3;
case(GL_RGB32I_EXT): return 3;
case(GL_RGB32UI_EXT): return 3;
case(GL_RGB16F_ARB): return 3;
case(GL_RGB32F_ARB): return 3;
case(GL_RGBA): return 4;
@@ -203,6 +260,12 @@ unsigned int Image::computeNumComponents(GLenum pixelFormat)
case(GL_LUMINANCE8): return 1;
case(GL_LUMINANCE12): return 1;
case(GL_LUMINANCE16): return 1;
case(GL_LUMINANCE8I_EXT): return 1;
case(GL_LUMINANCE8UI_EXT): return 1;
case(GL_LUMINANCE16I_EXT): return 1;
case(GL_LUMINANCE16UI_EXT): return 1;
case(GL_LUMINANCE32I_EXT): return 1;
case(GL_LUMINANCE32UI_EXT): return 1;
case(GL_LUMINANCE16F_ARB): return 1;
case(GL_LUMINANCE32F_ARB): return 1;
case(GL_LUMINANCE4_ALPHA4): return 2;
@@ -216,9 +279,21 @@ unsigned int Image::computeNumComponents(GLenum pixelFormat)
case(GL_INTENSITY8): return 1;
case(GL_INTENSITY12): return 1;
case(GL_INTENSITY16): return 1;
case(GL_INTENSITY8UI_EXT): return 1;
case(GL_INTENSITY8I_EXT): return 1;
case(GL_INTENSITY16I_EXT): return 1;
case(GL_INTENSITY16UI_EXT): return 1;
case(GL_INTENSITY32I_EXT): return 1;
case(GL_INTENSITY32UI_EXT): return 1;
case(GL_INTENSITY16F_ARB): return 1;
case(GL_INTENSITY32F_ARB): return 1;
case(GL_LUMINANCE_ALPHA): return 2;
case(GL_LUMINANCE_ALPHA8I_EXT): return 2;
case(GL_LUMINANCE_ALPHA8UI_EXT): return 2;
case(GL_LUMINANCE_ALPHA16I_EXT): return 2;
case(GL_LUMINANCE_ALPHA16UI_EXT): return 2;
case(GL_LUMINANCE_ALPHA32I_EXT): return 2;
case(GL_LUMINANCE_ALPHA32UI_EXT): return 2;
case(GL_LUMINANCE_ALPHA16F_ARB): return 2;
case(GL_LUMINANCE_ALPHA32F_ARB): return 2;
case(GL_HILO_NV): return 2;

View File

@@ -18,6 +18,7 @@
#include <osg/GLU>
#include <osg/Timer>
#include <osg/ApplicationUsage>
#include <osg/FrameBufferObject>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>
@@ -358,7 +359,8 @@ Texture::Texture():
_use_shadow_comparison(false),
_shadow_compare_func(LEQUAL),
_shadow_texture_mode(LUMINANCE),
_shadow_ambient(0)
_shadow_ambient(0),
_internalFormatType(NORMALIZED)
{
}
@@ -383,7 +385,8 @@ Texture::Texture(const Texture& text,const CopyOp& copyop):
_use_shadow_comparison(text._use_shadow_comparison),
_shadow_compare_func(text._shadow_compare_func),
_shadow_texture_mode(text._shadow_texture_mode),
_shadow_ambient(text._shadow_ambient)
_shadow_ambient(text._shadow_ambient),
_internalFormatType(text._internalFormatType)
{
}
@@ -422,6 +425,8 @@ int Texture::compareTexture(const Texture& rhs) const
COMPARE_StateAttribute_Parameter(_clientStorageHint)
COMPARE_StateAttribute_Parameter(_resizeNonPowerOfTwoHint)
COMPARE_StateAttribute_Parameter(_internalFormatType);
return 0;
}
@@ -492,6 +497,7 @@ void Texture::setMaxAnisotropy(float anis)
}
}
/** Force a recompile on next apply() of associated OpenGL texture objects.*/
void Texture::dirtyTextureObject()
{
@@ -513,10 +519,12 @@ void Texture::takeTextureObjects(Texture::TextureObjectListMap& toblm)
void Texture::dirtyTextureParameters()
{
for(unsigned int i=0;i<_texParametersDirtyList.size();++i)
{
_texParametersDirtyList[i] = 1;
}
_texParametersDirtyList.setAllElementsTo(1);
}
void Texture::allocateMipmapLevels()
{
_texMipmapGenerationDirtyList.setAllElementsTo(1);
}
void Texture::computeInternalFormatWithImage(const osg::Image& image) const
@@ -609,10 +617,88 @@ void Texture::computeInternalFormatWithImage(const osg::Image& image) const
}
_internalFormat = internalFormat;
computeInternalFormatType();
//osg::notify(osg::NOTICE)<<"Internal format="<<std::hex<<internalFormat<<std::dec<<std::endl;
}
void Texture::computeInternalFormatType() const
{
// Here we could also precompute the _sourceFormat if it is not set,
// since it is different for different internal formats
// (i.e. rgba integer texture --> _sourceFormat = GL_RGBA_INTEGER_EXT)
// Should we do this? ( Art, 09. Sept. 2007)
// compute internal format type based on the internal format
switch(_internalFormat)
{
case GL_RGBA32UI_EXT:
case GL_RGBA16UI_EXT:
case GL_RGBA8UI_EXT:
case GL_RGB32UI_EXT:
case GL_RGB16UI_EXT:
case GL_RGB8UI_EXT:
case GL_LUMINANCE32UI_EXT:
case GL_LUMINANCE16UI_EXT:
case GL_LUMINANCE8UI_EXT:
case GL_INTENSITY32UI_EXT:
case GL_INTENSITY16UI_EXT:
case GL_INTENSITY8UI_EXT:
case GL_LUMINANCE_ALPHA32UI_EXT:
case GL_LUMINANCE_ALPHA16UI_EXT:
case GL_LUMINANCE_ALPHA8UI_EXT :
_internalFormatType = UNSIGNED_INTEGER;
break;
case GL_RGBA32I_EXT:
case GL_RGBA16I_EXT:
case GL_RGBA8I_EXT:
case GL_RGB32I_EXT:
case GL_RGB16I_EXT:
case GL_RGB8I_EXT:
case GL_LUMINANCE32I_EXT:
case GL_LUMINANCE16I_EXT:
case GL_LUMINANCE8I_EXT:
case GL_INTENSITY32I_EXT:
case GL_INTENSITY16I_EXT:
case GL_INTENSITY8I_EXT:
case GL_LUMINANCE_ALPHA32I_EXT:
case GL_LUMINANCE_ALPHA16I_EXT:
case GL_LUMINANCE_ALPHA8I_EXT:
_internalFormatType = SIGNED_INTEGER;
break;
case GL_RGBA32F_ARB:
case GL_RGBA16F_ARB:
case GL_RGB32F_ARB:
case GL_RGB16F_ARB:
case GL_LUMINANCE32F_ARB:
case GL_LUMINANCE16F_ARB:
case GL_INTENSITY32F_ARB:
case GL_INTENSITY16F_ARB:
case GL_LUMINANCE_ALPHA32F_ARB:
case GL_LUMINANCE_ALPHA16F_ARB:
_internalFormatType = FLOAT;
break;
default:
_internalFormatType = NORMALIZED;
break;
};
}
bool Texture::isCompressedInternalFormat() const
{
return isCompressedInternalFormat(getInternalFormat());
@@ -703,7 +789,9 @@ void Texture::applyTexParameters(GLenum target, State& state) const
glTexParameteri( target, GL_TEXTURE_MIN_FILTER, _min_filter);
glTexParameteri( target, GL_TEXTURE_MAG_FILTER, _mag_filter);
if (extensions->isTextureFilterAnisotropicSupported())
// Art: I think anisotropic filtering is not supported by the integer textures
if (extensions->isTextureFilterAnisotropicSupported() &&
_internalFormatType != SIGNED_INTEGER && _internalFormatType != UNSIGNED_INTEGER)
{
// note, GL_TEXTURE_MAX_ANISOTROPY_EXT will either be defined
// by gl.h (or via glext.h) or by include/osg/Texture.
@@ -712,10 +800,23 @@ void Texture::applyTexParameters(GLenum target, State& state) const
if (extensions->isTextureBorderClampSupported())
{
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, _borderColor.ptr());
if (_internalFormatType == SIGNED_INTEGER)
{
GLint color[4] = {(GLint)_borderColor.r(), (GLint)_borderColor.g(), (GLint)_borderColor.b(), (GLint)_borderColor.a()};
extensions->glTexParameterIiv(target, GL_TEXTURE_BORDER_COLOR, color);
}else if (_internalFormatType == UNSIGNED_INTEGER)
{
GLuint color[4] = {(GLuint)_borderColor.r(), (GLuint)_borderColor.g(), (GLuint)_borderColor.b(), (GLuint)_borderColor.a()};
extensions->glTexParameterIuiv(target, GL_TEXTURE_BORDER_COLOR, color);
}else{
GLfloat color[4] = {(GLfloat)_borderColor.r(), (GLfloat)_borderColor.g(), (GLfloat)_borderColor.b(), (GLfloat)_borderColor.a()};
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color);
}
}
if (extensions->isShadowSupported() && target == GL_TEXTURE_2D)
// integer texture are not supported by the shadow
if (extensions->isShadowSupported() && target == GL_TEXTURE_2D &&
_internalFormatType != SIGNED_INTEGER && _internalFormatType != UNSIGNED_INTEGER)
{
if (_use_shadow_comparison)
{
@@ -1290,6 +1391,46 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
}
void Texture::generateMipmap(State& state) const
{
const unsigned int contextID = state.getContextID();
// get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID);
// if not initialized before, then do nothing
if (textureObject == NULL) return;
_texMipmapGenerationDirtyList[contextID] = 0;
// if internal format does not provide automatic mipmap generation, then do manual allocation
if (_internalFormatType == SIGNED_INTEGER || _internalFormatType == UNSIGNED_INTEGER)
{
allocateMipmap(state);
return;
}
// get fbo extension which provides us with the glGenerateMipmapEXT function
osg::FBOExtensions* fbo_ext = osg::FBOExtensions::instance(state.getContextID(), true);
// check if the function is supported
if (fbo_ext->glGenerateMipmapEXT)
{
textureObject->bind();
fbo_ext->glGenerateMipmapEXT(textureObject->_target);
// inform state that this texture is the current one bound.
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
// if the function is not supported, then do manual allocation
}else
{
allocateMipmap(state);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Static map to manage the deletion of texture objects are the right time.
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -1365,6 +1506,8 @@ Texture::Extensions::Extensions(const Extensions& rhs):
_isNonPowerOfTwoTextureMipMappedSupported = rhs._isNonPowerOfTwoTextureMipMappedSupported;
_isNonPowerOfTwoTextureNonMipMappedSupported = rhs._isNonPowerOfTwoTextureNonMipMappedSupported;
_isTextureIntegerEXTSupported = rhs._isTextureIntegerEXTSupported;
}
void Texture::Extensions::lowestCommonDenominator(const Extensions& rhs)
@@ -1395,6 +1538,8 @@ void Texture::Extensions::lowestCommonDenominator(const Extensions& rhs)
if (!rhs._isNonPowerOfTwoTextureMipMappedSupported) _isNonPowerOfTwoTextureMipMappedSupported = false;
if (!rhs._isNonPowerOfTwoTextureNonMipMappedSupported) _isNonPowerOfTwoTextureNonMipMappedSupported = false;
if (!rhs._isTextureIntegerEXTSupported) _isTextureIntegerEXTSupported = false;
}
void Texture::Extensions::setupGLExtensions(unsigned int contextID)
@@ -1438,6 +1583,8 @@ void Texture::Extensions::setupGLExtensions(unsigned int contextID)
_isNonPowerOfTwoTextureMipMappedSupported = _isNonPowerOfTwoTextureNonMipMappedSupported;
_isTextureIntegerEXTSupported = isGLExtensionSupported(contextID, "GL_EXT_texture_integer");
if (rendererString.find("Radeon")!=std::string::npos || rendererString.find("RADEON")!=std::string::npos)
{
_isNonPowerOfTwoTextureMipMappedSupported = false;
@@ -1473,9 +1620,40 @@ void Texture::Extensions::setupGLExtensions(unsigned int contextID)
_numTextureUnits = 1;
}
setGLExtensionFuncPtr(_glCompressedTexImage2D, "glCompressedTexImage2D","glCompressedTexImage2DARB");
setGLExtensionFuncPtr(_glCompressedTexSubImage2D, "glCompressedTexSubImage2D","glCompressedTexSubImage2DARB");
setGLExtensionFuncPtr(_glGetCompressedTexImage, "glGetCompressedTexImage","glGetCompressedTexImageARB");
setGLExtensionFuncPtr(_glCompressedTexImage2D,"glCompressedTexImage2D","glCompressedTexImage2DARB");
setGLExtensionFuncPtr(_glCompressedTexSubImage2D,"glCompressedTexSubImage2D","glCompressedTexSubImage2DARB");
setGLExtensionFuncPtr(_glGetCompressedTexImage,"glGetCompressedTexImage","glGetCompressedTexImageARB");;
setGLExtensionFuncPtr(_glTexParameterIiv, "glTexParameterIiv", "glTexParameterIivARB");
setGLExtensionFuncPtr(_glTexParameterIuiv, "glTexParameterIuiv", "glTexParameterIuivARB");
if (_glTexParameterIiv == NULL) setGLExtensionFuncPtr(_glTexParameterIiv, "glTexParameterIivEXT");
if (_glTexParameterIuiv == NULL) setGLExtensionFuncPtr(_glTexParameterIuiv, "glTexParameterIuivEXT");
}
void Texture::Extensions::glTexParameterIiv(GLenum target, GLenum pname, const GLint* data) const
{
if (_glTexParameterIiv)
{
_glTexParameterIiv(target, pname, data);
}
else
{
notify(WARN)<<"Error: glTexParameterIiv not supported by OpenGL driver"<<std::endl;
}
}
void Texture::Extensions::glTexParameterIuiv(GLenum target, GLenum pname, const GLuint* data) const
{
if (_glTexParameterIuiv)
{
_glTexParameterIuiv(target, pname, data);
}
else
{
notify(WARN)<<"Error: glTexParameterIuiv not supported by OpenGL driver"<<std::endl;
}
}
void Texture::Extensions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) const

View File

@@ -179,7 +179,7 @@ void Texture1D::apply(State& state) const
applyTexParameters(GL_TEXTURE_1D,state);
// no image present, but dimensions at set so lets create the texture
// no image present, but dimensions are set so lets create the texture
glTexImage1D( GL_TEXTURE_1D, 0, _internalFormat,
_textureWidth, _borderWidth,
_sourceFormat ? _sourceFormat : _internalFormat,
@@ -190,17 +190,24 @@ void Texture1D::apply(State& state) const
{
_readPBuffer->bindPBufferToTexture(GL_FRONT);
}
}
else
{
glBindTexture( GL_TEXTURE_1D, 0 );
}
// if texture object is now valid and we have to allocate mipmap levels, then
if (textureObject != 0 && _texMipmapGenerationDirtyList[contextID])
{
generateMipmap(state);
}
}
void Texture1D::computeInternalFormat() const
{
if (_image.valid()) computeInternalFormatWithImage(*_image);
else computeInternalFormatType();
}
void Texture1D::applyTexImage1D(GLenum target, Image* image, State& state, GLsizei& inwidth, GLsizei& numMipmapLevels) const
@@ -392,3 +399,40 @@ void Texture1D::copyTexSubImage1D(State& state, int xoffset, int x, int y, int w
copyTexImage1D(state,x,y,width);
}
}
void Texture1D::allocateMipmap(State& state) const
{
const unsigned int contextID = state.getContextID();
// get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID);
if (textureObject && _textureWidth != 0)
{
// bind texture
textureObject->bind();
// compute number of mipmap levels
int width = _textureWidth;
int numMipmapLevels = 1 + (int)floor(log2(width));
// we do not reallocate the level 0, since it was already allocated
width >>= 1;
for( GLsizei k = 1; k < numMipmapLevels && width; k++)
{
if (width == 0)
width = 1;
glTexImage1D( GL_TEXTURE_1D, k, _internalFormat,
width, _borderWidth,
_sourceFormat ? _sourceFormat : _internalFormat,
_sourceType ? _sourceType : GL_UNSIGNED_BYTE, NULL);
width >>= 1;
}
// inform state that this texture is the current one bound.
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
}
}

View File

@@ -193,13 +193,13 @@ void Texture2D::apply(State& state) const
if (textureObject->isAllocated())
{
//std::cout<<"Reusing texture object"<<std::endl;
//notify(NOTICE)<<"Reusing texture object"<<std::endl;
applyTexImage2D_subload(state,GL_TEXTURE_2D,image.get(),
_textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
}
else
{
//std::cout<<"Creating new texture object"<<std::endl;
//notify(NOTICE)<<"Creating new texture object"<<std::endl;
applyTexImage2D_load(state,GL_TEXTURE_2D,image.get(),
_textureWidth, _textureHeight, _numMipmapLevels);
@@ -250,14 +250,20 @@ void Texture2D::apply(State& state) const
{
glBindTexture( GL_TEXTURE_2D, 0 );
}
// if texture object is now valid and we have to allocate mipmap levels, then
if (textureObject != 0 && _texMipmapGenerationDirtyList[contextID])
{
generateMipmap(state);
}
}
void Texture2D::computeInternalFormat() const
{
if (_image.valid()) computeInternalFormatWithImage(*_image);
else computeInternalFormatType();
}
void Texture2D::copyTexImage2D(State& state, int x, int y, int width, int height )
{
const unsigned int contextID = state.getContextID();
@@ -386,3 +392,46 @@ void Texture2D::copyTexSubImage2D(State& state, int xoffset, int yoffset, int x,
copyTexImage2D(state,x,y,width,height);
}
}
void Texture2D::allocateMipmap(State& state) const
{
const unsigned int contextID = state.getContextID();
// get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID);
if (textureObject && _textureWidth != 0 && _textureHeight != 0)
{
// bind texture
textureObject->bind();
// compute number of mipmap levels
int width = _textureWidth;
int height = _textureHeight;
int numMipmapLevels = 1 + (int)floor(log2(maximum(width, height)));
// we do not reallocate the level 0, since it was already allocated
width >>= 1;
height >>= 1;
for( GLsizei k = 1; k < numMipmapLevels && (width || height); k++)
{
if (width == 0)
width = 1;
if (height == 0)
height = 1;
glTexImage2D( GL_TEXTURE_2D, k, _internalFormat,
width, height, _borderWidth,
_sourceFormat ? _sourceFormat : _internalFormat,
_sourceType ? _sourceType : GL_UNSIGNED_BYTE, NULL);
width >>= 1;
height >>= 1;
}
// inform state that this texture is the current one bound.
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
}
}

View File

@@ -167,6 +167,7 @@ bool Texture2DArray::imagesValid() const
void Texture2DArray::computeInternalFormat() const
{
if (imagesValid()) computeInternalFormatWithImage(*_images[0]);
else computeInternalFormatType();
}
@@ -299,6 +300,12 @@ void Texture2DArray::apply(State& state) const
{
glBindTexture( GL_TEXTURE_2D_ARRAY_EXT, 0 );
}
// if texture object is now valid and we have to allocate mipmap levels, then
if (textureObject != 0 && _texMipmapGenerationDirtyList[contextID])
{
generateMipmap(state);
}
}
void Texture2DArray::applyTexImage2DArray_subload(State& state, Image* image, GLsizei& inwidth, GLsizei& inheight, GLsizei& indepth, GLsizei& numMipmapLevels) const
@@ -385,27 +392,23 @@ void Texture2DArray::applyTexImage2DArray_subload(State& state, Image* image, GL
int width = image->s();
int height = image->t();
int depth = image->r();
for( GLsizei k = 0 ; k < numMipmapLevels && (width || height || depth) ;k++)
for( GLsizei k = 0 ; k < numMipmapLevels && (width || height ) ;k++)
{
if (width == 0)
width = 1;
if (height == 0)
height = 1;
if (depth == 0)
depth = 1;
extensions->glTexImage3D( target, k, _internalFormat,
width, height, depth, _borderWidth,
width, height, indepth, _borderWidth,
(GLenum)image->getPixelFormat(),
(GLenum)image->getDataType(),
image->getMipmapData(k));
width >>= 1;
height >>= 1;
depth >>= 1;
}
}
@@ -443,6 +446,51 @@ void Texture2DArray::copyTexSubImage2DArray(State& state, int xoffset, int yoffs
}
}
void Texture2DArray::allocateMipmap(State& state) const
{
const unsigned int contextID = state.getContextID();
// get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID);
if (textureObject && _textureWidth != 0 && _textureHeight != 0 && _textureDepth != 0)
{
const Extensions* extensions = getExtensions(contextID,true);
const Texture::Extensions* texExtensions = Texture::getExtensions(contextID,true);
// bind texture
textureObject->bind();
// compute number of mipmap levels
int width = _textureWidth;
int height = _textureHeight;
int numMipmapLevels = 1 + (int)floor(log2(maximum(width, height)));
// we do not reallocate the level 0, since it was already allocated
width >>= 1;
height >>= 1;
for( GLsizei k = 1; k < numMipmapLevels && (width || height); k++)
{
if (width == 0)
width = 1;
if (height == 0)
height = 1;
extensions->glTexImage3D( GL_TEXTURE_2D_ARRAY_EXT, k, _internalFormat,
width, height, _textureDepth, _borderWidth,
_sourceFormat ? _sourceFormat : _internalFormat,
_sourceType ? _sourceType : GL_UNSIGNED_BYTE, NULL);
width >>= 1;
height >>= 1;
}
// inform state that this texture is the current one bound.
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
}
}
typedef buffered_value< ref_ptr<Texture2DArray::Extensions> > BufferedExtensions;
static BufferedExtensions s_extensions;

View File

@@ -279,11 +279,18 @@ void Texture3D::apply(State& state) const
{
glBindTexture( GL_TEXTURE_3D, 0 );
}
// if texture object is now valid and we have to allocate mipmap levels, then
if (textureObject != 0 && _texMipmapGenerationDirtyList[contextID])
{
generateMipmap(state);
}
}
void Texture3D::computeInternalFormat() const
{
if (_image.valid()) computeInternalFormatWithImage(*_image);
else computeInternalFormatType();
}
void Texture3D::applyTexImage3D(GLenum target, Image* image, State& state, GLsizei& inwidth, GLsizei& inheight, GLsizei& indepth, GLsizei& numMipmapLevels) const
@@ -430,6 +437,56 @@ void Texture3D::copyTexSubImage3D(State& state, int xoffset, int yoffset, int zo
}
}
void Texture3D::allocateMipmap(State& state) const
{
const unsigned int contextID = state.getContextID();
// get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID);
if (textureObject && _textureWidth != 0 && _textureHeight != 0 && _textureDepth != 0)
{
const Extensions* extensions = getExtensions(contextID,true);
const Texture::Extensions* texExtensions = Texture::getExtensions(contextID,true);
// bind texture
textureObject->bind();
// compute number of mipmap levels
int width = _textureWidth;
int height = _textureHeight;
int depth = _textureDepth;
int numMipmapLevels = 1 + (int)floor(log2(maximum(width, maximum(depth, height))));
// we do not reallocate the level 0, since it was already allocated
width >>= 1;
height >>= 1;
depth >>= 1;
for( GLsizei k = 1; k < numMipmapLevels && (width || height || depth); k++)
{
if (width == 0)
width = 1;
if (height == 0)
height = 1;
if (depth == 0)
depth = 1;
extensions->glTexImage3D( GL_TEXTURE_3D, k, _internalFormat,
width, height, depth, _borderWidth,
_sourceFormat ? _sourceFormat : _internalFormat,
_sourceType ? _sourceType : GL_UNSIGNED_BYTE, NULL);
width >>= 1;
height >>= 1;
depth >>= 1;
}
// inform state that this texture is the current one bound.
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
}
}
typedef buffered_value< ref_ptr<Texture3D::Extensions> > BufferedExtensions;
static BufferedExtensions s_extensions;

View File

@@ -155,6 +155,7 @@ bool TextureCubeMap::imagesValid() const
void TextureCubeMap::computeInternalFormat() const
{
if (imagesValid()) computeInternalFormatWithImage(*_images[0]);
else computeInternalFormatType();
}
void TextureCubeMap::apply(State& state) const
@@ -289,6 +290,12 @@ void TextureCubeMap::apply(State& state) const
{
glBindTexture( GL_TEXTURE_CUBE_MAP, 0 );
}
// if texture object is now valid and we have to allocate mipmap levels, then
if (textureObject != 0 && _texMipmapGenerationDirtyList[contextID])
{
generateMipmap(state);
}
}
void TextureCubeMap::copyTexSubImageCubeMap(State& state, int face, int xoffset, int yoffset, int x, int y, int width, int height )
@@ -362,6 +369,51 @@ void TextureCubeMap::copyTexSubImageCubeMap(State& state, int face, int xoffset,
}
}
void TextureCubeMap::allocateMipmap(State& state) const
{
const unsigned int contextID = state.getContextID();
// get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID);
if (textureObject && _textureWidth != 0 && _textureHeight != 0)
{
// bind texture
textureObject->bind();
// compute number of mipmap levels
int width = _textureWidth;
int height = _textureHeight;
int numMipmapLevels = 1 + (int)floor(log2(maximum(width, height)));
// we do not reallocate the level 0, since it was already allocated
width >>= 1;
height >>= 1;
for( GLsizei k = 1; k < numMipmapLevels && (width || height); k++)
{
if (width == 0)
width = 1;
if (height == 0)
height = 1;
for (int n=0; n<6; n++)
{
glTexImage2D( faceTarget[n], k, _internalFormat,
width, height, _borderWidth,
_sourceFormat ? _sourceFormat : _internalFormat,
_sourceType ? _sourceType : GL_UNSIGNED_BYTE,
0);
}
width >>= 1;
height >>= 1;
}
// inform state that this texture is the current one bound.
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
}
}
typedef buffered_value< ref_ptr<TextureCubeMap::Extensions> > BufferedExtensions;
static BufferedExtensions s_extensions;

View File

@@ -409,8 +409,8 @@ void TextureRectangle::applyTexImage_subload(GLenum target, Image* image, State&
void TextureRectangle::computeInternalFormat() const
{
if (_image.valid())
computeInternalFormatWithImage(*_image);
if (_image.valid()) computeInternalFormatWithImage(*_image);
else computeInternalFormatType();
}
void TextureRectangle::copyTexImage2D(State& state, int x, int y, int width, int height )
@@ -542,3 +542,46 @@ void TextureRectangle::copyTexSubImage2D(State& state, int xoffset, int yoffset,
copyTexImage2D(state,x,y,width,height);
}
}
void TextureRectangle::allocateMipmap(State& state) const
{
const unsigned int contextID = state.getContextID();
// get the texture object for the current contextID.
TextureObject* textureObject = getTextureObject(contextID);
if (textureObject && _textureWidth != 0 && _textureHeight != 0)
{
// bind texture
textureObject->bind();
// compute number of mipmap levels
int width = _textureWidth;
int height = _textureHeight;
int numMipmapLevels = 1 + (int)floor(log2(maximum(width, height)));
// we do not reallocate the level 0, since it was already allocated
width >>= 1;
height >>= 1;
for( GLsizei k = 1; k < numMipmapLevels && (width || height); k++)
{
if (width == 0)
width = 1;
if (height == 0)
height = 1;
glTexImage2D( GL_TEXTURE_RECTANGLE, k, _internalFormat,
width, height, _borderWidth,
_sourceFormat ? _sourceFormat : _internalFormat,
_sourceType ? _sourceType : GL_UNSIGNED_BYTE, NULL);
width >>= 1;
height >>= 1;
}
// inform state that this texture is the current one bound.
state.haveAppliedTextureAttribute(state.getActiveTextureUnit(), this);
}
}

View File

@@ -17,7 +17,7 @@
#include <osg/State>
#include <osg/StateAttribute>
#include <osg/Texture>
#include <osg/Vec4>
#include <osg/Vec4d>
// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
@@ -73,6 +73,14 @@ BEGIN_ENUM_REFLECTOR(osg::Texture::InternalFormatMode)
I_EnumLabel(osg::Texture::USE_S3TC_DXT5_COMPRESSION);
END_REFLECTOR
BEGIN_ENUM_REFLECTOR(osg::Texture::InternalFormatType)
I_DeclaringFile("osg/Texture");
I_EnumLabel(osg::Texture::NORMALIZED);
I_EnumLabel(osg::Texture::FLOAT);
I_EnumLabel(osg::Texture::SIGNED_INTEGER);
I_EnumLabel(osg::Texture::UNSIGNED_INTEGER);
END_REFLECTOR
BEGIN_ENUM_REFLECTOR(osg::Texture::ShadowCompareFunc)
I_DeclaringFile("osg/Texture");
I_EnumLabel(osg::Texture::LEQUAL);
@@ -166,14 +174,14 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::Texture)
__WrapMode__getWrap__WrapParameter,
"Gets the texture wrap mode. ",
"");
I_Method1(void, setBorderColor, IN, const osg::Vec4 &, color,
I_Method1(void, setBorderColor, IN, const osg::Vec4d &, color,
Properties::NON_VIRTUAL,
__void__setBorderColor__C5_Vec4_R1,
__void__setBorderColor__C5_Vec4d_R1,
"Sets the border color. ",
"Only used when wrap mode is CLAMP_TO_BORDER. ");
I_Method0(const osg::Vec4 &, getBorderColor,
"Only used when wrap mode is CLAMP_TO_BORDER. The border color will be casted to the appropriate type to match the internal pixel format of the texture. ");
I_Method0(const osg::Vec4d &, getBorderColor,
Properties::NON_VIRTUAL,
__C5_Vec4_R1__getBorderColor,
__C5_Vec4d_R1__getBorderColor,
"Gets the border color. ",
"");
I_Method1(void, setBorderWidth, IN, GLint, width,
@@ -260,7 +268,7 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::Texture)
Properties::NON_VIRTUAL,
__void__setInternalFormat__GLint,
"Sets the internal texture format. ",
"Implicitly sets the internalFormatMode to USE_USER_DEFINED_FORMAT. ");
"Implicitly sets the internalFormatMode to USE_USER_DEFINED_FORMAT. The corresponding internal format type will be computed. ");
I_Method0(GLint, getInternalFormat,
Properties::NON_VIRTUAL,
__GLint__getInternalFormat,
@@ -291,6 +299,11 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::Texture)
__GLenum__getSourceType,
"Gets the external source data type. ",
"");
I_Method0(osg::Texture::InternalFormatType, getInternalFormatType,
Properties::NON_VIRTUAL,
__InternalFormatType__getInternalFormatType,
"Get the internal texture format type. ",
"");
I_Method1(osg::Texture::TextureObject *, getTextureObject, IN, unsigned int, contextID,
Properties::NON_VIRTUAL,
__TextureObject_P1__getTextureObject__unsigned_int,
@@ -316,6 +329,11 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::Texture)
__void__dirtyTextureParameters,
"Force a reset on next apply() of associated OpenGL texture parameters. ",
"");
I_Method0(void, allocateMipmapLevels,
Properties::NON_VIRTUAL,
__void__allocateMipmapLevels,
"Force a manual allocation of the mipmap levels on the next apply() call. ",
"User is responsible for filling the mipmap levels with valid data. The OpenGL's glGenerateMipmapEXT function is used to generate the mipmap levels. If glGenerateMipmapEXT is not supported or texture's internal format is not supported by the glGenerateMipmapEXT, then empty mipmap levels will be allocated manualy. The mipmap levels are also allocated if a non-mipmapped min filter is used. ");
I_Method1(void, setShadowComparison, IN, bool, flag,
Properties::NON_VIRTUAL,
__void__setShadowComparison__bool,
@@ -479,12 +497,30 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::Texture)
__void__computeRequiredTextureDimensions__State_R1__C5_osg_Image_R1__GLsizei_R1__GLsizei_R1__GLsizei_R1,
"",
"");
I_ProtectedMethod0(void, computeInternalFormatType,
Properties::NON_VIRTUAL,
Properties::CONST,
__void__computeInternalFormatType,
"",
"");
I_ProtectedMethod2(void, applyTexParameters, IN, GLenum, target, IN, osg::State &, state,
Properties::NON_VIRTUAL,
Properties::CONST,
__void__applyTexParameters__GLenum__State_R1,
"Helper method. ",
"Sets texture paramters. ");
I_ProtectedMethod1(void, generateMipmap, IN, osg::State &, state,
Properties::NON_VIRTUAL,
Properties::CONST,
__void__generateMipmap__State_R1,
"Helper method to generate empty mipmap levels by calling of glGenerateMipmapEXT. ",
"If it is not supported, then call the virtual allocateMipmap() method ");
I_ProtectedMethod1(void, allocateMipmap, IN, osg::State &, state,
Properties::PURE_VIRTUAL,
Properties::CONST,
__void__allocateMipmap__State_R1,
"Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. ",
"");
I_ProtectedMethod1(int, compareTexture, IN, const osg::Texture &, rhs,
Properties::NON_VIRTUAL,
Properties::CONST,
@@ -497,9 +533,9 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::Texture)
__int__compareTextureObjects__C5_Texture_R1,
"Returns -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. ",
"");
I_SimpleProperty(const osg::Vec4 &, BorderColor,
__C5_Vec4_R1__getBorderColor,
__void__setBorderColor__C5_Vec4_R1);
I_SimpleProperty(const osg::Vec4d &, BorderColor,
__C5_Vec4d_R1__getBorderColor,
__void__setBorderColor__C5_Vec4d_R1);
I_SimpleProperty(GLint, BorderWidth,
__GLint__getBorderWidth,
__void__setBorderWidth__GLint);
@@ -523,6 +559,9 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::Texture)
I_SimpleProperty(osg::Texture::InternalFormatMode, InternalFormatMode,
__InternalFormatMode__getInternalFormatMode,
__void__setInternalFormatMode__InternalFormatMode);
I_SimpleProperty(osg::Texture::InternalFormatType, InternalFormatType,
__InternalFormatType__getInternalFormatType,
0);
I_SimpleProperty(float, MaxAnisotropy,
__float__getMaxAnisotropy,
__void__setMaxAnisotropy__float);
@@ -755,6 +794,26 @@ BEGIN_OBJECT_REFLECTOR(osg::Texture::Extensions)
__bool__isNonPowerOfTwoTextureSupported__GLenum,
"",
"");
I_Method1(void, setTextureIntegerEXTSupported, IN, bool, flag,
Properties::NON_VIRTUAL,
__void__setTextureIntegerEXTSupported__bool,
"",
"");
I_Method0(bool, isTextureIntegerEXTSupported,
Properties::NON_VIRTUAL,
__bool__isTextureIntegerEXTSupported,
"",
"");
I_Method3(void, glTexParameterIiv, IN, GLenum, target, IN, GLenum, pname, IN, const GLint *, data,
Properties::NON_VIRTUAL,
__void__glTexParameterIiv__GLenum__GLenum__C5_GLint_P1,
"",
"");
I_Method3(void, glTexParameterIuiv, IN, GLenum, target, IN, GLenum, pname, IN, const GLuint *, data,
Properties::NON_VIRTUAL,
__void__glTexParameterIuiv__GLenum__GLenum__C5_GLuint_P1,
"",
"");
@@ -791,6 +850,9 @@ BEGIN_OBJECT_REFLECTOR(osg::Texture::Extensions)
I_SimpleProperty(bool, TextureFilterAnisotropicSupported,
0,
__void__setTextureFilterAnisotropicSupported__bool);
I_SimpleProperty(bool, TextureIntegerEXTSupported,
0,
__void__setTextureIntegerEXTSupported__bool);
I_SimpleProperty(bool, TextureMirroredRepeatSupported,
0,
__void__setTextureMirroredRepeatSupported__bool);

View File

@@ -181,6 +181,12 @@ BEGIN_OBJECT_REFLECTOR(osg::Texture1D)
__void__computeInternalFormat,
"",
"");
I_ProtectedMethod1(void, allocateMipmap, IN, osg::State &, state,
Properties::VIRTUAL,
Properties::CONST,
__void__allocateMipmap__State_R1,
"Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. ",
"");
I_ProtectedMethod5(void, applyTexImage1D, IN, GLenum, target, IN, osg::Image *, image, IN, osg::State &, state, IN, GLsizei &, width, IN, GLsizei &, numMipmapLevels,
Properties::NON_VIRTUAL,
Properties::CONST,

View File

@@ -196,6 +196,12 @@ BEGIN_OBJECT_REFLECTOR(osg::Texture2D)
__void__computeInternalFormat,
"",
"");
I_ProtectedMethod1(void, allocateMipmap, IN, osg::State &, state,
Properties::VIRTUAL,
Properties::CONST,
__void__allocateMipmap__State_R1,
"Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. ",
"");
I_SimpleProperty(osg::Image *, Image,
__Image_P1__getImage,
__void__setImage__Image_P1);

View File

@@ -190,6 +190,12 @@ BEGIN_OBJECT_REFLECTOR(osg::Texture2DArray)
__void__computeInternalFormat,
"",
"");
I_ProtectedMethod1(void, allocateMipmap, IN, osg::State &, state,
Properties::VIRTUAL,
Properties::CONST,
__void__allocateMipmap__State_R1,
"Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. ",
"");
I_ProtectedMethod6(void, applyTexImage2DArray_subload, IN, osg::State &, state, IN, osg::Image *, image, IN, GLsizei &, inwidth, IN, GLsizei &, inheight, IN, GLsizei &, indepth, IN, GLsizei &, numMipmapLevels,
Properties::NON_VIRTUAL,
Properties::CONST,

View File

@@ -210,6 +210,12 @@ BEGIN_OBJECT_REFLECTOR(osg::Texture3D)
__void__computeInternalFormat,
"",
"");
I_ProtectedMethod1(void, allocateMipmap, IN, osg::State &, state,
Properties::VIRTUAL,
Properties::CONST,
__void__allocateMipmap__State_R1,
"Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. ",
"");
I_ProtectedMethod7(void, applyTexImage3D, IN, GLenum, target, IN, osg::Image *, image, IN, osg::State &, state, IN, GLsizei &, inwidth, IN, GLsizei &, inheight, IN, GLsizei &, indepth, IN, GLsizei &, numMipmapLevels,
Properties::NON_VIRTUAL,
Properties::CONST,

View File

@@ -195,6 +195,12 @@ BEGIN_OBJECT_REFLECTOR(osg::TextureCubeMap)
__void__computeInternalFormat,
"",
"");
I_ProtectedMethod1(void, allocateMipmap, IN, osg::State &, state,
Properties::VIRTUAL,
Properties::CONST,
__void__allocateMipmap__State_R1,
"Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. ",
"");
I_ArrayProperty(osg::Image *, Image,
__Image_P1__getImage__unsigned_int,
__void__setImage__unsigned_int__Image_P1,

View File

@@ -186,6 +186,12 @@ BEGIN_OBJECT_REFLECTOR(osg::TextureRectangle)
__void__computeInternalFormat,
"",
"");
I_ProtectedMethod1(void, allocateMipmap, IN, osg::State &, state,
Properties::VIRTUAL,
Properties::CONST,
__void__allocateMipmap__State_R1,
"Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. ",
"");
I_ProtectedMethod2(void, applyTexParameters, IN, GLenum, target, IN, osg::State &, state,
Properties::NON_VIRTUAL,
Properties::CONST,