0030748: Visualization - Marker displayed in immediate layer ruins QT Quick view...
[occt.git] / src / OpenGl / OpenGl_Texture.cxx
index 5af1708..a87bb9f 100644 (file)
@@ -1,10 +1,10 @@
 // Created by: Kirill GAVRILOV
-// Copyright (c) 2014 OPEN CASCADE SAS
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
 
 #include <OpenGl_Texture.hxx>
 
-#include <OpenGl_ExtFBO.hxx>
+#include <OpenGl_ArbFBO.hxx>
 #include <OpenGl_Context.hxx>
+#include <OpenGl_GlCore32.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <Graphic3d_TextureParams.hxx>
+#include <TCollection_ExtendedString.hxx>
 #include <Standard_Assert.hxx>
 #include <Image_PixMap.hxx>
 
-IMPLEMENT_STANDARD_HANDLE (OpenGl_Texture, OpenGl_Resource)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_Resource)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_NamedResource)
 
 //! Simple class to reset unpack alignment settings
 struct OpenGl_UnpackAlignmentSentry
 {
 
   //! Reset unpack alignment settings to safe values
-  void Reset()
+  static void Reset()
   {
     glPixelStorei (GL_UNPACK_ALIGNMENT,  1);
+  #if !defined(GL_ES_VERSION_2_0)
     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+  #endif
   }
 
+  OpenGl_UnpackAlignmentSentry() {}
+
   ~OpenGl_UnpackAlignmentSentry()
   {
     Reset();
@@ -45,20 +51,23 @@ struct OpenGl_UnpackAlignmentSentry
 // function : OpenGl_Texture
 // purpose  :
 // =======================================================================
-OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
-: OpenGl_Resource(),
+OpenGl_Texture::OpenGl_Texture (const TCollection_AsciiString& theResourceId,
+                                const Handle(Graphic3d_TextureParams)& theParams)
+: OpenGl_NamedResource (theResourceId),
+  mySampler (new OpenGl_Sampler (theParams)),
+  myRevision (0),
   myTextureId (NO_TEXTURE),
   myTarget (GL_TEXTURE_2D),
   mySizeX (0),
   mySizeY (0),
-  myTextFormat (GL_FLOAT),
+  mySizeZ (0),
+  myTextFormat (GL_RGBA),
+  mySizedFormat(GL_RGBA8),
+  myNbSamples  (1),
   myHasMipmaps (Standard_False),
-  myParams     (theParams)
+  myIsAlpha    (false)
 {
-  if (myParams.IsNull())
-  {
-    myParams = new Graphic3d_TextureParams();
-  }
+  //
 }
 
 // =======================================================================
@@ -70,52 +79,34 @@ OpenGl_Texture::~OpenGl_Texture()
   Release (NULL);
 }
 
-// =======================================================================
-// function : HasMipmaps
-// purpose  :
-// =======================================================================
-const Standard_Boolean OpenGl_Texture::HasMipmaps() const
-{
-  return myHasMipmaps;
-}
-
-// =======================================================================
-// function : GetParams
-// purpose  :
-// =======================================================================
-const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
-{
-  return myParams;
-}
-
-// =======================================================================
-// function : SetParams
-// purpose  :
-// =======================================================================
-void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
-{
-  myParams = theParams;
-}
-
 // =======================================================================
 // function : Create
 // purpose  :
 // =======================================================================
-bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
+bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& theCtx)
 {
+  if (myTextureId != NO_TEXTURE)
+  {
+    return true;
+  }
+
+  theCtx->core11fwd->glGenTextures (1, &myTextureId);
   if (myTextureId == NO_TEXTURE)
   {
-    glGenTextures (1, &myTextureId);
+    return false;
   }
-  return myTextureId != NO_TEXTURE;
+
+  //mySampler->Create (theCtx); // do not create sampler object by default
+  return true;
 }
 
 // =======================================================================
 // function : Release
 // purpose  :
 // =======================================================================
-void OpenGl_Texture::Release (const OpenGl_Context* theGlCtx)
+void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
 {
+  mySampler->Release (theGlCtx);
   if (myTextureId == NO_TEXTURE)
   {
     return;
@@ -130,7 +121,20 @@ void OpenGl_Texture::Release (const OpenGl_Context* theGlCtx)
     glDeleteTextures (1, &myTextureId);
   }
   myTextureId = NO_TEXTURE;
-  mySizeX = mySizeY = 0;
+  mySizeX = mySizeY = mySizeZ = 0;
+}
+
+// =======================================================================
+// function : applyDefaultSamplerParams
+// purpose  :
+// =======================================================================
+void OpenGl_Texture::applyDefaultSamplerParams (const Handle(OpenGl_Context)& theCtx)
+{
+  OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), NULL, myTarget, myHasMipmaps);
+  if (mySampler->IsValid() && !mySampler->IsImmutable())
+  {
+    OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), mySampler.get(), myTarget, myHasMipmaps);
+  }
 }
 
 // =======================================================================
@@ -138,12 +142,13 @@ void OpenGl_Texture::Release (const OpenGl_Context* theGlCtx)
 // purpose  :
 // =======================================================================
 void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
-                           const GLenum theTextureUnit) const
+                           const Graphic3d_TextureUnit   theTextureUnit) const
 {
-  if (theCtx->IsGlGreaterEqual (1, 3))
+  if (theCtx->core15fwd != NULL)
   {
-    theCtx->core13->glActiveTexture (theTextureUnit);
+    theCtx->core15fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
   }
+  mySampler->Bind (theCtx, theTextureUnit);
   glBindTexture (myTarget, myTextureId);
 }
 
@@ -152,337 +157,915 @@ void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
 // purpose  :
 // =======================================================================
 void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
-                             const GLenum theTextureUnit) const
+                             const Graphic3d_TextureUnit   theTextureUnit) const
 {
-  if (theCtx->IsGlGreaterEqual (1, 3))
+  if (theCtx->core15fwd != NULL)
   {
-    theCtx->core13->glActiveTexture (theTextureUnit);
+    theCtx->core15fwd->glActiveTexture (GL_TEXTURE0 + theTextureUnit);
   }
+  mySampler->Unbind (theCtx, theTextureUnit);
   glBindTexture (myTarget, NO_TEXTURE);
 }
 
-// =======================================================================
-// function : Init
-// purpose  :
-// =======================================================================
-bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
-                           const Image_PixMap&           theImage,
-                           const Graphic3d_TypeOfTexture theType)
+//=======================================================================
+//function : InitSamplerObject
+//purpose  :
+//=======================================================================
+bool OpenGl_Texture::InitSamplerObject (const Handle(OpenGl_Context)& theCtx)
 {
-  myHasMipmaps = Standard_False;
-  if (theImage.IsEmpty() || !Create (theCtx))
-  {
-    return false;
-  }
+  return myTextureId != NO_TEXTURE
+      && mySampler->Init (theCtx, *this);
+}
 
-  myTextFormat = GL_RGBA8;
-  GLenum aPixelFormat = 0;
-  GLenum aDataType    = 0;
-  switch (theImage.Format())
+//=======================================================================
+//function : GetDataFormat
+//purpose  :
+//=======================================================================
+bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
+                                    const Image_PixMap&           theData,
+                                    GLint&                        theTextFormat,
+                                    GLenum&                       thePixelFormat,
+                                    GLenum&                       theDataType)
+{
+  theTextFormat  = GL_RGBA8;
+  thePixelFormat = 0;
+  theDataType    = 0;
+  switch (theData.Format())
   {
-    case Image_PixMap::ImgGrayF:
+    case Image_Format_GrayF:
     {
-      myTextFormat = GL_ALPHA8; // GL_R8, GL_R32F
-      aPixelFormat = GL_ALPHA;  // GL_RED
-      aDataType    = GL_FLOAT;
-      break;
+      if (theCtx->core11 == NULL)
+      {
+        theTextFormat  = GL_R8;  // GL_R32F
+        thePixelFormat = GL_RED;
+      }
+      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::ImgRGBAF:
+    case Image_Format_AlphaF:
     {
-      myTextFormat = GL_RGBA8; // GL_RGBA32F
-      aPixelFormat = GL_RGBA;
-      aDataType    = GL_FLOAT;
-      break;
+      if (theCtx->core11 == NULL)
+      {
+        theTextFormat  = GL_R8;  // GL_R32F
+        thePixelFormat = GL_RED;
+      }
+      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_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)
       {
         return false;
       }
-      myTextFormat = GL_RGBA8; // GL_RGBA32F
-      aPixelFormat = GL_BGRA;  // equals to GL_BGRA_EXT
-      aDataType    = GL_FLOAT;
-      break;
+      theTextFormat  = GL_RGBA8;    // GL_RGBA32F
+      thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
+      theDataType    = GL_FLOAT;
+      return true;
     }
-    case Image_PixMap::ImgRGBF:
+    case Image_Format_RGBF:
     {
-      myTextFormat = GL_RGB8; // GL_RGB32F
-      aPixelFormat = GL_RGB;
-      aDataType    = GL_FLOAT;
-      break;
+      theTextFormat  = GL_RGB8; // GL_RGB32F
+      thePixelFormat = GL_RGB;
+      theDataType    = GL_FLOAT;
+      return true;
     }
-    case Image_PixMap::ImgBGRF:
+    case Image_Format_BGRF:
     {
-      myTextFormat = GL_RGB8; // GL_RGB32F
-      aPixelFormat = GL_BGR;  // equals to GL_BGR_EXT
-      aDataType    = GL_FLOAT;
-      break;
+    #if !defined(GL_ES_VERSION_2_0)
+      theTextFormat  = GL_RGB8; // GL_RGB32F
+      thePixelFormat = GL_BGR;  // equals to GL_BGR_EXT
+      theDataType    = GL_FLOAT;
+      return true;
+    #else
+      return false;
+    #endif
     }
-    case Image_PixMap::ImgRGBA:
+    case Image_Format_RGBA:
     {
-      myTextFormat = GL_RGBA8;
-      aPixelFormat = GL_RGBA;
-      aDataType    = GL_UNSIGNED_BYTE;
-      break;
+      theTextFormat = GL_RGBA8;
+      thePixelFormat = GL_RGBA;
+      theDataType    = GL_UNSIGNED_BYTE;
+      return true;
     }
-    case Image_PixMap::ImgBGRA:
+    case Image_Format_BGRA:
     {
+    #if !defined(GL_ES_VERSION_2_0)
       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
       {
         return false;
       }
-      myTextFormat = GL_RGBA8;
-      aPixelFormat = GL_BGRA;  // equals to GL_BGRA_EXT
-      aDataType    = GL_UNSIGNED_BYTE;
-      break;
+      theTextFormat  = GL_RGBA8;
+    #else
+      if (!theCtx->extBgra)
+      {
+        return false;
+      }
+      theTextFormat  = GL_BGRA_EXT;
+    #endif
+      thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
+      theDataType    = GL_UNSIGNED_BYTE;
+      return true;
     }
-    case Image_PixMap::ImgRGB32:
+    case Image_Format_RGB32:
     {
-      myTextFormat = GL_RGB8;
-      aPixelFormat = GL_RGBA;
-      aDataType    = GL_UNSIGNED_BYTE;
-      break;
+    #if !defined(GL_ES_VERSION_2_0)
+      // ask driver to convert data to RGB8 to save memory
+      theTextFormat  = GL_RGB8;
+    #else
+      // conversion is not supported
+      theTextFormat  = GL_RGBA8;
+    #endif
+      thePixelFormat = GL_RGBA;
+      theDataType    = GL_UNSIGNED_BYTE;
+      return true;
     }
-    case Image_PixMap::ImgBGR32:
+    case Image_Format_BGR32:
     {
-      if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
+    #if !defined(GL_ES_VERSION_2_0)
+      if (!theCtx->IsGlGreaterEqual(1, 2) && !theCtx->extBgra)
+      {
+        return false;
+      }
+      theTextFormat  = GL_RGB8;
+    #else
+      if (!theCtx->extBgra)
       {
         return false;
       }
-      myTextFormat = GL_RGB8;
-      aPixelFormat = GL_BGRA;  // equals to GL_BGRA_EXT
-      aDataType    = GL_UNSIGNED_BYTE;
-      break;
+      theTextFormat  = GL_BGRA_EXT;
+    #endif
+      thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
+      theDataType    = GL_UNSIGNED_BYTE;
+      return true;
     }
-    case Image_PixMap::ImgRGB:
+    case Image_Format_RGB:
     {
-      myTextFormat = GL_RGB8;
-      aPixelFormat = GL_RGB;
-      aDataType    = GL_UNSIGNED_BYTE;
-      break;
+      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;
       }
-      myTextFormat = GL_RGB8;
-      aPixelFormat = GL_BGR;  // equals to GL_BGR_EXT
-      aDataType    = GL_UNSIGNED_BYTE;
-      break;
+      theTextFormat = GL_RGB8;
+      thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
+      theDataType    = GL_UNSIGNED_BYTE;
+      return true;
+    #else
+      return false;
+    #endif
     }
-    case Image_PixMap::ImgGray:
+    case Image_Format_Gray:
     {
-      myTextFormat = GL_ALPHA8; // GL_R8
-      aPixelFormat = GL_ALPHA;  // GL_RED
-      aDataType    = GL_UNSIGNED_BYTE;
-      break;
+      if (theCtx->core11 == NULL)
+      {
+        theTextFormat  = GL_R8;
+        thePixelFormat = GL_RED;
+      }
+      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;
     }
-    default:
+    case Image_Format_Alpha:
     {
+      if (theCtx->core11 == NULL)
+      {
+        theTextFormat  = GL_R8;
+        thePixelFormat = GL_RED;
+      }
+      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_Format_UNKNOWN:
+    {
+      return false;
+    }
+  }
+  return false;
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
+                           const Standard_Integer        theTextFormat,
+                           const GLenum                  thePixelFormat,
+                           const GLenum                  theDataType,
+                           const Standard_Integer        theSizeX,
+                           const Standard_Integer        theSizeY,
+                           const Graphic3d_TypeOfTexture theType,
+                           const Image_PixMap*           theImage)
+{
+  if (theSizeX < 1
+   || theSizeY < 1)
+  {
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                         "Error: texture of 0 size cannot be created.");
+    Release (theCtx.operator->());
+    return false;
+  }
+
+#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->());
+    return false;
+  }
+
+  if (theImage != NULL)
+  {
+    myIsAlpha = theImage->Format() == Image_Format_Alpha
+             || theImage->Format() == Image_Format_AlphaF;
+  }
+  else
+  {
+    myIsAlpha = thePixelFormat == GL_ALPHA;
+  }
+
+  myHasMipmaps             = toCreateMipMaps;
+  myTextFormat             = thePixelFormat;
+  mySizedFormat            = theTextFormat;
+  myNbSamples              = 1;
+#if !defined(GL_ES_VERSION_2_0)
+  const GLint anIntFormat  = theTextFormat;
+#else
+  // 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
+
+  if (theDataType == GL_FLOAT && !theCtx->arbTexFloat)
+  {
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                         "Error: floating-point textures are not supported by hardware.");
+    Release (theCtx.operator->());
+    return false;
+  }
+
+  const GLsizei aMaxSize = theCtx->MaxTextureSize();
+  if (theSizeX > aMaxSize
+   || theSizeY > aMaxSize)
+  {
+    TCollection_ExtendedString aWarnMessage = TCollection_ExtendedString ("Error: Texture dimension - ")
+      + 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->());
+    return false;
+  }
+#if !defined(GL_ES_VERSION_2_0)
+  else if (!theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW)
+  {
+    // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
+    // 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 (theSizeX, aMaxSize);
+    const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (theSizeY, aMaxSize);
+
+    if (theSizeX != aWidthP2
+     || (theType != Graphic3d_TOT_1D && theSizeY != aHeightP2))
+    {
+      TCollection_ExtendedString aWarnMessage =
+        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);
+
+      Release (theCtx.operator->());
       return false;
     }
   }
+#else
+  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 (theSizeX, aMaxSize);
+    const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (theSizeY, aMaxSize);
 
-  const GLsizei aMaxSize   = theCtx->MaxTextureSize();
-  const GLsizei aWidth     = (GLsizei )theImage.SizeX();
-  const GLsizei aHeight    = (GLsizei )theImage.SizeY();
+    if (theSizeX != aWidthP2
+     || theSizeY != aHeightP2)
+    {
+      TCollection_ExtendedString aWarnMessage =
+        TCollection_ExtendedString ("Error: Mipmap NPOT Textures (") + theSizeX + "x" + theSizeY + ") are not supported by OpenGL ES 2.0";
 
-  // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
-  // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
-  // Trying to create NPOT rextures on such hardware will not fail
-  // but driver will fall back into software rendering,
-  const bool    toForceP2  = !theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW;
-  const GLsizei aWidthOut  = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aWidth,  aMaxSize) : Min (aWidth,  aMaxSize);
-  const GLsizei aHeightOut = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize) : Min (aHeight, aMaxSize);
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
 
+      Release (theCtx.operator->());
+      return false;
+    }
+  }
+#endif
+
+#if !defined(GL_ES_VERSION_2_0)
   GLint aTestWidth  = 0;
   GLint aTestHeight = 0;
+#endif
+  GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
 
   // setup the alignment
   OpenGl_UnpackAlignmentSentry anUnpackSentry;
-  const GLint anAligment = Min ((GLint )theImage.MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
-  glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
+  (void)anUnpackSentry; // avoid compiler warning
 
-  // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
-  const GLint anExtraBytes = GLint(theImage.RowExtraBytes());
-  const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
-  glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
+  if (aDataPtr != NULL)
+  {
+    const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
+    glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
 
+  #if !defined(GL_ES_VERSION_2_0)
+    // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
+    const GLint anExtraBytes = GLint(theImage->RowExtraBytes());
+    const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes());
+    glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
+  #endif
+  }
+
+  myTarget = aTarget;
   switch (theType)
   {
     case Graphic3d_TOT_1D:
     {
-      myTarget = GL_TEXTURE_1D;
+    #if !defined(GL_ES_VERSION_2_0)
       Bind (theCtx);
-      glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
-      Image_PixMap aCopy;
-      GLvoid* aDataPtr = (GLvoid* )theImage.Data();
-      if (aWidth != aWidthOut)
+      applyDefaultSamplerParams (theCtx);
+      if (toPatchExisting)
       {
-        glPixelStorei (GL_PACK_ALIGNMENT,  1);
-        glPixelStorei (GL_PACK_ROW_LENGTH, 0);
-        if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), 1)
-          || gluScaleImage (aPixelFormat,
-                            aWidth,    1, aDataType, theImage.Data(),
-                            aWidthOut, 1, aDataType, aCopy.ChangeData()) != 0)
-        {
-          Unbind (theCtx);
-          return false;
-        }
-
-        aDataPtr = (GLvoid* )aCopy.Data();
-        anUnpackSentry.Reset();
+        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, myTextFormat,
-                    aWidthOut, 0,
-                    aPixelFormat, aDataType, NULL);
-      glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
+      glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
+                    theSizeX, 0,
+                    thePixelFormat, theDataType, NULL);
+      glGetTexLevelParameteriv (GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
+      glGetTexLevelParameteriv (GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
       if (aTestWidth == 0)
       {
         // no memory or broken input parameters
         Unbind (theCtx);
+        Release (theCtx.operator->());
         return false;
       }
 
-      glTexImage1D (GL_TEXTURE_1D, 0, myTextFormat,
-                    aWidthOut, 0,
-                    aPixelFormat, aDataType, aDataPtr);
+      glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
+                    theSizeX, 0,
+                    thePixelFormat, theDataType, aDataPtr);
       if (glGetError() != GL_NO_ERROR)
       {
         Unbind (theCtx);
+        Release (theCtx.operator->());
         return false;
       }
 
-      mySizeX = aWidthOut;
+      mySizeX = theSizeX;
       mySizeY = 1;
 
       Unbind (theCtx);
       return true;
+    #else
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                           "Error: 1D textures are not supported by hardware.");
+      Release (theCtx.operator->());
+      return false;
+    #endif
     }
     case Graphic3d_TOT_2D:
     {
-      myTarget = GL_TEXTURE_2D;
       Bind (theCtx);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-      Image_PixMap aCopy;
-      GLvoid* aDataPtr = (GLvoid* )theImage.Data();
-      if (aWidth != aWidthOut || aHeight != aHeightOut)
+      applyDefaultSamplerParams (theCtx);
+      if (toPatchExisting)
       {
-        // scale texture
-        glPixelStorei (GL_PACK_ALIGNMENT,  1);
-        glPixelStorei (GL_PACK_ROW_LENGTH, 0);
-        if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut))
-          || gluScaleImage (aPixelFormat,
-                            aWidth,    aHeight,    aDataType, theImage.Data(),
-                            aWidthOut, aHeightOut, aDataType, aCopy.ChangeData()) != 0)
-        {
-          Unbind (theCtx);
-          return false;
-        }
-
-        aDataPtr = (GLvoid* )aCopy.Data();
-        anUnpackSentry.Reset();
+        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, myTextFormat,
-                    aWidthOut, aHeightOut, 0,
-                    aPixelFormat, aDataType, NULL);
+      glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
+                    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);
+      glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
       if (aTestWidth == 0 || aTestHeight == 0)
       {
         // no memory or broken input parameters
         Unbind (theCtx);
+        Release (theCtx.operator->());
         return false;
       }
+    #endif
 
-      glTexImage2D (GL_TEXTURE_2D, 0, myTextFormat,
-                    aWidthOut, aHeightOut, 0,
-                    aPixelFormat, aDataType, aDataPtr);
-      if (glGetError() != GL_NO_ERROR)
+      glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
+                    theSizeX, theSizeY, 0,
+                    thePixelFormat, theDataType, aDataPtr);
+      const GLenum anErr = glGetError();
+      if (anErr != GL_NO_ERROR)
       {
+        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                             TCollection_AsciiString ("Error: 2D texture ") + theSizeX + "x" + theSizeY
+                                                   + " IF: " + int(anIntFormat) + " PF: " + int(thePixelFormat) + " DT: " + int(theDataType)
+                                                   + " can not be created with error " + int(anErr) + ".");
         Unbind (theCtx);
+        Release (theCtx.operator->());
         return false;
       }
 
-      mySizeX = aWidthOut;
-      mySizeY = aHeightOut;
+      mySizeX = theSizeX;
+      mySizeY = theSizeY;
 
       Unbind (theCtx);
       return true;
     }
     case Graphic3d_TOT_2D_MIPMAP:
     {
-      myTarget     = GL_TEXTURE_2D;
-      myHasMipmaps = Standard_True;
       Bind (theCtx);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-      if (theCtx->extFBO != NULL
-       && aWidth == aWidthOut && aHeight == aHeightOut)
+      applyDefaultSamplerParams (theCtx);
+      if (toPatchExisting)
       {
-        // use proxy to check texture could be created or not
-        glTexImage2D (GL_PROXY_TEXTURE_2D, 0, myTextFormat,
-                      aWidthOut, aHeightOut, 0,
-                      aPixelFormat, aDataType, NULL);
-        glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &aTestWidth);
-        glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
-        if (aTestWidth == 0 || aTestHeight == 0)
+        glTexSubImage2D (GL_TEXTURE_2D, 0,
+                         0, 0,
+                         theSizeX, theSizeY,
+                         thePixelFormat, theDataType, aDataPtr);
+        if (theCtx->arbFBO != NULL)
         {
-          // no memory or broken input parameters
-          Unbind (theCtx);
-          return false;
+          // generate mipmaps
+          theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
+          if (glGetError() != GL_NO_ERROR)
+          {
+            Unbind (theCtx);
+            Release (theCtx.operator->());
+            return false;
+          }
         }
 
-        // upload main picture
-        glTexImage2D (GL_TEXTURE_2D, 0, myTextFormat,
-                      aWidthOut, aHeightOut, 0,
-                      aPixelFormat, aDataType, theImage.Data());
-        if (glGetError() != GL_NO_ERROR)
-        {
-          Unbind (theCtx);
-          return false;
-        }
+        Unbind (theCtx);
+        return true;
+      }
 
-        mySizeX = aWidthOut;
-        mySizeY = aHeightOut;
+    #if !defined(GL_ES_VERSION_2_0)
+      // use proxy to check texture could be created or not
+      glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
+                    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);
+      glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
+      if (aTestWidth == 0 || aTestHeight == 0)
+      {
+        // no memory or broken input parameters
+        Unbind (theCtx);
+        Release (theCtx.operator->());
+        return false;
+      }
+    #endif
 
+      // upload main picture
+      glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
+                    theSizeX, theSizeY, 0,
+                    thePixelFormat, theDataType, theImage->Data());
+      const GLenum aTexImgErr = glGetError();
+      if (aTexImgErr != GL_NO_ERROR)
+      {
+        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                             TCollection_AsciiString ("Error: 2D texture ") + theSizeX + "x" + theSizeY
+                                                    + " IF: " + int(anIntFormat) + " PF: " + int(thePixelFormat) + " DT: " + int(theDataType)
+                                                    + " can not be created with error " + int(aTexImgErr) + ".");
+        Unbind (theCtx);
+        Release (theCtx.operator->());
+        return false;
+      }
+
+      mySizeX = theSizeX;
+      mySizeY = theSizeY;
+
+      if (theCtx->arbFBO != NULL)
+      {
         // generate mipmaps
         //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
-        theCtx->extFBO->glGenerateMipmapEXT (GL_TEXTURE_2D);
+        theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
 
-        Unbind (theCtx);
-        return true;
+        if (glGetError() != GL_NO_ERROR)
+        {
+          Unbind (theCtx);
+          Release (theCtx.operator->());
+          return false;
+        }
       }
       else
       {
-        bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, myTextFormat,
-                                            aWidth, aHeight,
-                                            aPixelFormat, aDataType, theImage.Data()) == 0;
-        if (isCreated)
-        {
-          glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &mySizeX);
-          glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &mySizeY);
-        }
+        const TCollection_ExtendedString aWarnMessage ("Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
+
+        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
 
         Unbind (theCtx);
-        return isCreated;
+        Release (theCtx.operator->());
+        return false;
       }
+
+      Unbind (theCtx);
+      return true;
     }
-    default:
-    {
-      return false;
-    }
   }
+
+  Release (theCtx.operator->());
+  return false;
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
+                           const Image_PixMap&           theImage,
+                           const Graphic3d_TypeOfTexture theType)
+{
+  if (theImage.IsEmpty())
+  {
+    Release (theCtx.operator->());
+    return false;
+  }
+
+  GLenum aPixelFormat;
+  GLenum aDataType;
+  GLint aTextFormat;
+  if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType))
+  {
+    Release (theCtx.operator->());
+    return false;
+  }
+
+  return Init (theCtx,
+               aTextFormat, aPixelFormat, aDataType,
+               (Standard_Integer)theImage.SizeX(),
+               (Standard_Integer)theImage.SizeY(),
+               theType, &theImage);
+}
+
+// =======================================================================
+// function : Init2DMultisample
+// purpose  :
+// =======================================================================
+bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx,
+                                        const GLsizei                 theNbSamples,
+                                        const GLint                   theTextFormat,
+                                        const GLsizei                 theSizeX,
+                                        const GLsizei                 theSizeY)
+{
+  if (!Create (theCtx)
+    || theNbSamples > theCtx->MaxMsaaSamples()
+    || theNbSamples < 1)
+  {
+    return false;
+  }
+
+  myNbSamples = OpenGl_Context::GetPowerOfTwo (theNbSamples, theCtx->MaxMsaaSamples());
+  myTarget = GL_TEXTURE_2D_MULTISAMPLE;
+  myHasMipmaps = false;
+  if(theSizeX > theCtx->MaxTextureSize()
+  || theSizeY > theCtx->MaxTextureSize())
+  {
+    return false;
+  }
+
+  Bind (theCtx);
+  //myTextFormat = theTextFormat;
+  mySizedFormat = theTextFormat;
+#if !defined(GL_ES_VERSION_2_0)
+  if (theCtx->Functions()->glTexStorage2DMultisample != NULL)
+  {
+    theCtx->Functions()->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
+  }
+  else
+  {
+    theCtx->Functions()->glTexImage2DMultisample   (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
+  }
+#else
+  theCtx->Functions()  ->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
+#endif
+  if (theCtx->core11fwd->glGetError() != GL_NO_ERROR)
+  {
+    Unbind (theCtx);
+    return false;
+  }
+
+  mySizeX = theSizeX;
+  mySizeY = theSizeY;
+
+  Unbind (theCtx);
+  return true;
+}
+
+// =======================================================================
+// function : InitRectangle
+// purpose  :
+// =======================================================================
+bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
+                                    const Standard_Integer        theSizeX,
+                                    const Standard_Integer        theSizeY,
+                                    const OpenGl_TextureFormat&   theFormat)
+{
+  if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (3, 0))
+  {
+    return false;
+  }
+
+#if !defined(GL_ES_VERSION_2_0)
+  myTarget = GL_TEXTURE_RECTANGLE;
+  myNbSamples = 1;
+  myHasMipmaps = false;
+
+  const GLsizei aSizeX    = Min (theCtx->MaxTextureSize(), theSizeX);
+  const GLsizei aSizeY    = Min (theCtx->MaxTextureSize(), theSizeY);
+
+  Bind (theCtx);
+  applyDefaultSamplerParams (theCtx);
+
+  myTextFormat  = theFormat.Format();
+  mySizedFormat = theFormat.Internal();
+
+  // setup the alignment
+  OpenGl_UnpackAlignmentSentry::Reset();
+
+  glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE, 0, mySizedFormat,
+                aSizeX, aSizeY, 0,
+                myTextFormat, GL_FLOAT, NULL);
+
+  GLint aTestSizeX = 0;
+  GLint aTestSizeY = 0;
+
+  glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH,  &aTestSizeX);
+  glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
+  glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
+
+  if (aTestSizeX == 0 || aTestSizeY == 0)
+  {
+    Unbind (theCtx);
+    return false;
+  }
+
+  glTexImage2D (myTarget, 0, mySizedFormat,
+                aSizeX, aSizeY, 0,
+                myTextFormat, GL_FLOAT, NULL);
+
+  if (glGetError() != GL_NO_ERROR)
+  {
+    Unbind (theCtx);
+    return false;
+  }
+
+  mySizeX = aSizeX;
+  mySizeY = aSizeY;
+
+  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;
+  myNbSamples = 1;
+  myHasMipmaps = false;
+
+  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;
+  }
+
+  mySizedFormat = theTextFormat;
+
+  // setup the alignment
+  OpenGl_UnpackAlignmentSentry::Reset();
+
+#if !defined (GL_ES_VERSION_2_0)
+  theCtx->core15fwd->glTexImage3D (GL_PROXY_TEXTURE_3D, 0, mySizedFormat,
+                                   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);
+  glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
+
+  if (aTestSizeX == 0 || aTestSizeY == 0 || aTestSizeZ == 0)
+  {
+    Unbind (theCtx);
+    Release (theCtx.operator->());
+    return false;
+  }
+#endif
+
+  applyDefaultSamplerParams (theCtx);
+  theCtx->Functions()->glTexImage3D (myTarget, 0, mySizedFormat,
+                                     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;
+}
+
+// =======================================================================
+// function : PixelSizeOfPixelFormat
+// purpose  :
+// =======================================================================
+Standard_Size OpenGl_Texture::PixelSizeOfPixelFormat (Standard_Integer theInternalFormat)
+{
+  switch(theInternalFormat)
+  {
+    // RED variations (GL_RED, OpenGL 3.0+)
+    case GL_RED:
+    case GL_R8:       return 1;
+    case GL_R16:      return 2;
+    case GL_R16F:     return 2;
+    case GL_R32F:     return 4;
+    // RGB variations
+    case GL_RGB:      return 3;
+    case GL_RGB8:     return 3;
+    case GL_RGB16:    return 6;
+    case GL_RGB16F:   return 6;
+    case GL_RGB32F:   return 12;
+    // RGBA variations
+    case GL_RGBA:     return 4;
+    case GL_RGBA8:    return 4;
+    case GL_RGB10_A2: return 4;
+    case GL_RGBA12:   return 6;
+    case GL_RGBA16:   return 8;
+    case GL_RGBA16F:  return 8;
+    case GL_RGBA32F:  return 16;
+    //
+    case GL_BGRA_EXT:  return 4;
+    // ALPHA variations (deprecated)
+    case GL_ALPHA:
+    case GL_ALPHA8:    return 1;
+    case GL_ALPHA16:   return 2;
+    case GL_LUMINANCE: return 1;
+    case GL_LUMINANCE_ALPHA: return 2;
+    // depth-stencil
+    case GL_DEPTH24_STENCIL8:   return 4;
+    case GL_DEPTH32F_STENCIL8:  return 8;
+    case GL_DEPTH_COMPONENT16:  return 2;
+    case GL_DEPTH_COMPONENT24:  return 3;
+    case GL_DEPTH_COMPONENT32F: return 4;
+  }
+  return 0;
+}
+
+// =======================================================================
+// function : EstimatedDataSize
+// purpose  :
+// =======================================================================
+Standard_Size OpenGl_Texture::EstimatedDataSize() const
+{
+  if (!IsValid())
+  {
+    return 0;
+  }
+
+  Standard_Size aSize = PixelSizeOfPixelFormat (mySizedFormat) * mySizeX * myNbSamples;
+  if (mySizeY != 0)
+  {
+    aSize *= Standard_Size(mySizeY);
+  }
+  if (mySizeZ != 0)
+  {
+    aSize *= Standard_Size(mySizeZ);
+  }
+  if (myHasMipmaps)
+  {
+    aSize = aSize + aSize / 3;
+  }
+  return aSize;
 }