// =======================================================================
OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
: OpenGl_Resource(),
+ myRevision (0),
myTextureId (NO_TEXTURE),
myTarget (GL_TEXTURE_2D),
mySizeX (0),
mySizeY (0),
+ mySizeZ (0),
myTextFormat (GL_RGBA),
myHasMipmaps (Standard_False),
myIsAlpha (false),
glDeleteTextures (1, &myTextureId);
}
myTextureId = NO_TEXTURE;
- mySizeX = mySizeY = 0;
+ mySizeX = mySizeY = mySizeZ = 0;
}
// =======================================================================
theDataType = 0;
switch (theData.Format())
{
- case Image_PixMap::ImgGrayF:
+ case Image_Format_GrayF:
{
if (theCtx->core11 == NULL)
{
}
else
{
+ #if !defined(GL_ES_VERSION_2_0)
theTextFormat = GL_LUMINANCE8;
+ #else
+ theTextFormat = GL_LUMINANCE;
+ #endif
thePixelFormat = GL_LUMINANCE;
}
theDataType = GL_FLOAT;
return true;
}
- case Image_PixMap::ImgAlphaF:
+ case Image_Format_AlphaF:
{
if (theCtx->core11 == NULL)
{
}
else
{
+ #if !defined(GL_ES_VERSION_2_0)
theTextFormat = GL_ALPHA8;
+ #else
+ theTextFormat = GL_ALPHA;
+ #endif
thePixelFormat = GL_ALPHA;
}
theDataType = GL_FLOAT;
return true;
}
- case Image_PixMap::ImgRGBAF:
+ case Image_Format_RGBAF:
{
theTextFormat = GL_RGBA8; // GL_RGBA32F
thePixelFormat = GL_RGBA;
theDataType = GL_FLOAT;
return true;
}
- case Image_PixMap::ImgBGRAF:
+ case Image_Format_BGRAF:
{
if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
{
theDataType = GL_FLOAT;
return true;
}
- case Image_PixMap::ImgRGBF:
+ case Image_Format_RGBF:
{
theTextFormat = GL_RGB8; // GL_RGB32F
thePixelFormat = GL_RGB;
theDataType = GL_FLOAT;
return true;
}
- case Image_PixMap::ImgBGRF:
+ case Image_Format_BGRF:
{
#if !defined(GL_ES_VERSION_2_0)
theTextFormat = GL_RGB8; // GL_RGB32F
return false;
#endif
}
- case Image_PixMap::ImgRGBA:
+ case Image_Format_RGBA:
{
theTextFormat = GL_RGBA8;
thePixelFormat = GL_RGBA;
theDataType = GL_UNSIGNED_BYTE;
return true;
}
- case Image_PixMap::ImgBGRA:
+ case Image_Format_BGRA:
{
if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
{
theDataType = GL_UNSIGNED_BYTE;
return true;
}
- case Image_PixMap::ImgRGB32:
+ case Image_Format_RGB32:
{
theTextFormat = GL_RGB8;
thePixelFormat = GL_RGBA;
theDataType = GL_UNSIGNED_BYTE;
return true;
}
- case Image_PixMap::ImgBGR32:
+ case Image_Format_BGR32:
{
if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
{
theDataType = GL_UNSIGNED_BYTE;
return true;
}
- case Image_PixMap::ImgRGB:
+ case Image_Format_RGB:
{
theTextFormat = GL_RGB8;
thePixelFormat = GL_RGB;
theDataType = GL_UNSIGNED_BYTE;
return true;
}
- case Image_PixMap::ImgBGR:
+ case Image_Format_BGR:
{
#if !defined(GL_ES_VERSION_2_0)
if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
return false;
#endif
}
- case Image_PixMap::ImgGray:
+ case Image_Format_Gray:
{
if (theCtx->core11 == NULL)
{
}
else
{
+ #if !defined(GL_ES_VERSION_2_0)
theTextFormat = GL_LUMINANCE8;
+ #else
+ theTextFormat = GL_LUMINANCE;
+ #endif
thePixelFormat = GL_LUMINANCE;
}
theDataType = GL_UNSIGNED_BYTE;
return true;
}
- case Image_PixMap::ImgAlpha:
+ case Image_Format_Alpha:
{
if (theCtx->core11 == NULL)
{
}
else
{
+ #if !defined(GL_ES_VERSION_2_0)
theTextFormat = GL_ALPHA8;
+ #else
+ theTextFormat = GL_ALPHA;
+ #endif
thePixelFormat = GL_ALPHA;
}
theDataType = GL_UNSIGNED_BYTE;
return true;
}
- case Image_PixMap::ImgUNKNOWN:
+ case Image_Format_UNKNOWN:
{
return false;
}
const Graphic3d_TypeOfTexture theType,
const Image_PixMap* theImage)
{
+#if !defined(GL_ES_VERSION_2_0)
+ const GLenum aTarget = theType == Graphic3d_TOT_1D
+ ? GL_TEXTURE_1D
+ : GL_TEXTURE_2D;
+#else
+ const GLenum aTarget = GL_TEXTURE_2D;
+#endif
+ const Standard_Boolean toCreateMipMaps = (theType == Graphic3d_TOT_2D_MIPMAP);
+ const bool toPatchExisting = IsValid()
+ && myTextFormat == thePixelFormat
+ && myTarget == aTarget
+ && myHasMipmaps == toCreateMipMaps
+ && mySizeX == theSizeX
+ && (mySizeY == theSizeY || theType == Graphic3d_TOT_1D);
if (!Create (theCtx))
{
Release (theCtx.operator->());
if (theImage != NULL)
{
- myIsAlpha = theImage->Format() == Image_PixMap::ImgAlpha
- || theImage->Format() == Image_PixMap::ImgAlphaF;
+ myIsAlpha = theImage->Format() == Image_Format_Alpha
+ || theImage->Format() == Image_Format_AlphaF;
}
else
{
myIsAlpha = thePixelFormat == GL_ALPHA;
}
- myHasMipmaps = Standard_False;
+ myHasMipmaps = toCreateMipMaps;
myTextFormat = thePixelFormat;
#if !defined(GL_ES_VERSION_2_0)
const GLint anIntFormat = theTextFormat;
#else
- // ES does not support sized formats and format conversions - them detected from data type
- const GLint anIntFormat = thePixelFormat;
+ // ES 2.0 does not support sized formats and format conversions - them detected from data type
+ const GLint anIntFormat = theCtx->IsGlGreaterEqual (3, 0) ? theTextFormat : thePixelFormat;
#endif
- const GLsizei aWidth = theSizeX;
- const GLsizei aHeight = theSizeY;
- const GLsizei aMaxSize = theCtx->MaxTextureSize();
- if (aWidth > aMaxSize || aHeight > aMaxSize)
+ const GLsizei aMaxSize = theCtx->MaxTextureSize();
+ if (theSizeX > aMaxSize
+ || theSizeY > aMaxSize)
{
TCollection_ExtendedString aWarnMessage = TCollection_ExtendedString ("Error: Texture dimension - ")
- + aWidth + "x" + aHeight + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")";
+ + theSizeX + "x" + theSizeY + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")";
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
Release (theCtx.operator->());
// however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
// Trying to create NPOT textures on such hardware will not fail
// but driver will fall back into software rendering,
- const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize);
- const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize);
+ const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (theSizeX, aMaxSize);
+ const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (theSizeY, aMaxSize);
- if (aWidth != aWidthP2 || (theType != Graphic3d_TOT_1D && aHeight != aHeightP2))
+ if (theSizeX != aWidthP2
+ || (theType != Graphic3d_TOT_1D && theSizeY != aHeightP2))
{
TCollection_ExtendedString aWarnMessage =
- TCollection_ExtendedString ("Error: NPOT Textures (") + aWidth + "x" + aHeight + ") are not supported by hardware.";
+ TCollection_ExtendedString ("Error: NPOT Textures (") + theSizeX + "x" + theSizeY + ") are not supported by hardware.";
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
else if (!theCtx->IsGlGreaterEqual (3, 0) && theType == Graphic3d_TOT_2D_MIPMAP)
{
// Mipmap NPOT textures are not supported by OpenGL ES 2.0.
- const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize);
- const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize);
+ const GLsizei aWidthP2 = OpenGl_Context::GetPowerOfTwo (theSizeX, aMaxSize);
+ const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (theSizeY, aMaxSize);
- if (aWidth != aWidthP2 || aHeight != aHeightP2)
+ if (theSizeX != aWidthP2
+ || theSizeY != aHeightP2)
{
TCollection_ExtendedString aWarnMessage =
- TCollection_ExtendedString ("Error: Mipmap NPOT Textures (") + aWidth + "x" + aHeight + ") are not supported by OpenGL ES 2.0";
+ TCollection_ExtendedString ("Error: Mipmap NPOT Textures (") + theSizeX + "x" + theSizeY + ") are not supported by OpenGL ES 2.0";
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
#endif
}
+ myTarget = aTarget;
switch (theType)
{
case Graphic3d_TOT_1D:
{
#if !defined(GL_ES_VERSION_2_0)
- myTarget = GL_TEXTURE_1D;
Bind (theCtx);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode);
+ if (toPatchExisting)
+ {
+ glTexSubImage1D (GL_TEXTURE_1D, 0, 0,
+ theSizeX, thePixelFormat, theDataType, aDataPtr);
+ Unbind (theCtx);
+ return true;
+ }
// use proxy to check texture could be created or not
glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
- aWidth, 0,
+ theSizeX, 0,
thePixelFormat, theDataType, NULL);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
if (aTestWidth == 0)
}
glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
- aWidth, 0,
+ theSizeX, 0,
thePixelFormat, theDataType, aDataPtr);
if (glGetError() != GL_NO_ERROR)
{
return false;
}
- mySizeX = aWidth;
+ mySizeX = theSizeX;
mySizeY = 1;
Unbind (theCtx);
}
case Graphic3d_TOT_2D:
{
- myTarget = GL_TEXTURE_2D;
Bind (theCtx);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilter);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode);
+ if (toPatchExisting)
+ {
+ glTexSubImage2D (GL_TEXTURE_2D, 0,
+ 0, 0,
+ theSizeX, theSizeY,
+ thePixelFormat, theDataType, aDataPtr);
+ Unbind (theCtx);
+ return true;
+ }
#if !defined(GL_ES_VERSION_2_0)
// use proxy to check texture could be created or not
glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
- aWidth, aHeight, 0,
+ theSizeX, theSizeY, 0,
thePixelFormat, theDataType, NULL);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
#endif
glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
- aWidth, aHeight, 0,
+ theSizeX, theSizeY, 0,
thePixelFormat, theDataType, aDataPtr);
if (glGetError() != GL_NO_ERROR)
{
return false;
}
- mySizeX = aWidth;
- mySizeY = aHeight;
+ mySizeX = theSizeX;
+ mySizeY = theSizeY;
Unbind (theCtx);
return true;
}
case Graphic3d_TOT_2D_MIPMAP:
{
- myTarget = GL_TEXTURE_2D;
- myHasMipmaps = Standard_True;
-
GLenum aFilterMin = aFilter;
aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
if (myParams->Filter() == Graphic3d_TOTF_BILINEAR)
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode);
+ if (toPatchExisting)
+ {
+ glTexSubImage2D (GL_TEXTURE_2D, 0,
+ 0, 0,
+ theSizeX, theSizeY,
+ thePixelFormat, theDataType, aDataPtr);
+ if (theCtx->arbFBO != NULL)
+ {
+ // generate mipmaps
+ theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
+ if (glGetError() != GL_NO_ERROR)
+ {
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+ }
+
+ Unbind (theCtx);
+ return true;
+ }
#if !defined(GL_ES_VERSION_2_0)
// use proxy to check texture could be created or not
glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
- aWidth, aHeight, 0,
+ theSizeX, theSizeY, 0,
thePixelFormat, theDataType, NULL);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
// upload main picture
glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
- aWidth, aHeight, 0,
+ theSizeX, theSizeY, 0,
thePixelFormat, theDataType, theImage->Data());
if (glGetError() != GL_NO_ERROR)
{
return false;
}
- mySizeX = aWidth;
- mySizeY = aHeight;
+ mySizeX = theSizeX;
+ mySizeY = theSizeY;
if (theCtx->arbFBO != NULL)
{
Unbind (theCtx);
return true;
}
- default:
- {
- Release (theCtx.operator->());
- return false;
- }
}
+
+ Release (theCtx.operator->());
+ return false;
}
// =======================================================================
Unbind (theCtx);
return true;
#else
+ (void )theSizeX;
+ (void )theSizeY;
+ (void )theFormat;
return false;
#endif
}
+
+// =======================================================================
+// function : Init3D
+// purpose :
+// =======================================================================
+bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx,
+ const GLint theTextFormat,
+ const GLenum thePixelFormat,
+ const GLenum theDataType,
+ const Standard_Integer theSizeX,
+ const Standard_Integer theSizeY,
+ const Standard_Integer theSizeZ,
+ const void* thePixels)
+{
+ if (theCtx->Functions()->glTexImage3D == NULL)
+ {
+ TCollection_ExtendedString aMsg ("Error: three-dimensional textures are not supported by hardware.");
+
+ theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+ GL_DEBUG_TYPE_ERROR,
+ 0,
+ GL_DEBUG_SEVERITY_HIGH,
+ aMsg);
+
+ return false;
+ }
+
+ if (!Create(theCtx))
+ {
+ return false;
+ }
+
+ myTarget = GL_TEXTURE_3D;
+
+ const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
+ const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
+ const GLsizei aSizeZ = Min (theCtx->MaxTextureSize(), theSizeZ);
+
+ Bind (theCtx);
+
+ if (theDataType == GL_FLOAT && !theCtx->arbTexFloat)
+ {
+ TCollection_ExtendedString aMsg ("Error: floating-point textures are not supported by hardware.");
+
+ theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+ GL_DEBUG_TYPE_ERROR,
+ 0,
+ GL_DEBUG_SEVERITY_HIGH,
+ aMsg);
+
+ Release (theCtx.operator->());
+ Unbind (theCtx);
+ return false;
+ }
+
+ const GLint anIntFormat = theTextFormat;
+
+#if !defined (GL_ES_VERSION_2_0)
+ theCtx->core15fwd->glTexImage3D (GL_PROXY_TEXTURE_3D,
+ 0,
+ anIntFormat,
+ aSizeX,
+ aSizeY,
+ aSizeZ,
+ 0,
+ thePixelFormat,
+ theDataType,
+ NULL);
+
+ GLint aTestSizeX = 0;
+ GLint aTestSizeY = 0;
+ GLint aTestSizeZ = 0;
+
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &aTestSizeZ);
+
+ if (aTestSizeX == 0 || aTestSizeY == 0 || aTestSizeZ == 0)
+ {
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+#endif
+
+ const GLenum aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
+ const GLenum aFilter = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
+
+ glTexParameteri (myTarget, GL_TEXTURE_WRAP_S, aWrapMode);
+ glTexParameteri (myTarget, GL_TEXTURE_WRAP_T, aWrapMode);
+ glTexParameteri (myTarget, GL_TEXTURE_WRAP_R, aWrapMode);
+
+ glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, aFilter);
+ glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, aFilter);
+
+ theCtx->Functions()->glTexImage3D (myTarget,
+ 0,
+ anIntFormat,
+ aSizeX,
+ aSizeY,
+ aSizeZ,
+ 0,
+ thePixelFormat,
+ theDataType,
+ thePixels);
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+
+ mySizeX = aSizeX;
+ mySizeY = aSizeY;
+ mySizeZ = aSizeZ;
+
+ Unbind (theCtx);
+ return true;
+}