// Created by: Kirill GAVRILOV
-// Copyright (c) 2012 OPEN CASCADE SAS
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
//
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
//
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// 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.
//
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
#include <OpenGl_Texture.hxx>
+#include <OpenGl_ArbFBO.hxx>
#include <OpenGl_Context.hxx>
+#include <OpenGl_GlCore15.hxx>
#include <Graphic3d_TextureParams.hxx>
#include <Standard_Assert.hxx>
#include <Image_PixMap.hxx>
IMPLEMENT_STANDARD_HANDLE (OpenGl_Texture, OpenGl_Resource)
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_Resource)
-//! Function for getting power of to number larger or equal to input number.
-//! @param theNumber number to 'power of two'
-//! @param theThreshold upper threshold
-//! @return power of two number
-inline GLsizei getPowerOfTwo (const GLsizei theNumber,
- const GLsizei theThreshold)
+//! Simple class to reset unpack alignment settings
+struct OpenGl_UnpackAlignmentSentry
{
- for (GLsizei p2 = 2; p2 <= theThreshold; p2 <<= 1)
+
+ //! Reset unpack alignment settings to safe values
+ void Reset()
{
- if (theNumber <= p2)
- {
- return p2;
- }
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ #if !defined(GL_ES_VERSION_2_0)
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+ #endif
}
- return theThreshold;
-}
+
+ ~OpenGl_UnpackAlignmentSentry()
+ {
+ Reset();
+ }
+
+};
// =======================================================================
// function : OpenGl_Texture
myTarget (GL_TEXTURE_2D),
mySizeX (0),
mySizeY (0),
- myTextFormat (GL_FLOAT),
+ myTextFormat (GL_RGBA),
myHasMipmaps (Standard_False),
myParams (theParams)
{
// function : Release
// purpose :
// =======================================================================
-void OpenGl_Texture::Release (const OpenGl_Context* theGlCtx)
+void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
{
if (myTextureId == NO_TEXTURE)
{
Standard_ASSERT_RETURN (theGlCtx != NULL,
"OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
- glDeleteTextures (1, &myTextureId);
+ if (theGlCtx->IsValid())
+ {
+ glDeleteTextures (1, &myTextureId);
+ }
myTextureId = NO_TEXTURE;
mySizeX = mySizeY = 0;
}
void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
const GLenum theTextureUnit) const
{
- if (theCtx->IsGlGreaterEqual (1, 3))
+ if (theCtx->IsGlGreaterEqual (1, 5))
{
- theCtx->core13->glActiveTexture (theTextureUnit);
+ theCtx->core15fwd->glActiveTexture (theTextureUnit);
}
glBindTexture (myTarget, myTextureId);
}
void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
const GLenum theTextureUnit) const
{
- if (theCtx->IsGlGreaterEqual (1, 3))
+ if (theCtx->IsGlGreaterEqual (1, 5))
{
- theCtx->core13->glActiveTexture (theTextureUnit);
+ theCtx->core15fwd->glActiveTexture (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 : GetDataFormat
+//purpose :
+//=======================================================================
+bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
+ const Image_PixMap& theData,
+ GLint& theTextFormat,
+ GLenum& thePixelFormat,
+ GLenum& theDataType)
{
- myHasMipmaps = Standard_False;
- if (theImage.IsEmpty() || !Create (theCtx))
- {
- return false;
- }
-
- GLenum aTextureFormat = GL_RGBA8;
- GLenum aPixelFormat = 0;
- GLenum aDataType = 0;
- switch (theImage.Format())
+ theTextFormat = GL_RGBA8;
+ thePixelFormat = 0;
+ theDataType = 0;
+ switch (theData.Format())
{
case Image_PixMap::ImgGrayF:
{
- aTextureFormat = GL_ALPHA8; // GL_R8, GL_R32F
- aPixelFormat = GL_ALPHA; // GL_RED
- aDataType = GL_FLOAT;
- break;
+ theTextFormat = GL_ALPHA8; // GL_R8, GL_R32F
+ thePixelFormat = GL_ALPHA; // GL_RED
+ theDataType = GL_FLOAT;
+ return true;
}
case Image_PixMap::ImgRGBAF:
{
- aTextureFormat = GL_RGBA8; // GL_RGBA32F
- aPixelFormat = GL_RGBA;
- aDataType = GL_FLOAT;
- break;
+ theTextFormat = GL_RGBA8; // GL_RGBA32F
+ thePixelFormat = GL_RGBA;
+ theDataType = GL_FLOAT;
+ return true;
}
case Image_PixMap::ImgBGRAF:
{
{
return false;
}
- aTextureFormat = 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:
{
- aTextureFormat = 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:
{
- aTextureFormat = 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:
{
- aTextureFormat = 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:
{
{
return false;
}
- aTextureFormat = GL_RGBA8;
- aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
- aDataType = GL_UNSIGNED_BYTE;
- break;
+ theTextFormat = GL_RGBA8;
+ thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
+ theDataType = GL_UNSIGNED_BYTE;
+ return true;
}
case Image_PixMap::ImgRGB32:
{
- aTextureFormat = GL_RGB8;
- aPixelFormat = GL_RGBA;
- aDataType = GL_UNSIGNED_BYTE;
- break;
+ theTextFormat = GL_RGB8;
+ thePixelFormat = GL_RGBA;
+ theDataType = GL_UNSIGNED_BYTE;
+ return true;
}
case Image_PixMap::ImgBGR32:
{
{
return false;
}
- aTextureFormat = GL_RGB8;
- aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
- aDataType = GL_UNSIGNED_BYTE;
- break;
+ theTextFormat = GL_RGB8;
+ thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
+ theDataType = GL_UNSIGNED_BYTE;
+ return true;
}
case Image_PixMap::ImgRGB:
{
- aTextureFormat = 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:
{
+ #if !defined(GL_ES_VERSION_2_0)
if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
{
return false;
}
- aTextureFormat = 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:
{
- aTextureFormat = GL_ALPHA8; // GL_R8
- aPixelFormat = GL_ALPHA; // GL_RED
- aDataType = GL_UNSIGNED_BYTE;
- break;
+ theTextFormat = GL_ALPHA8; // GL_R8
+ thePixelFormat = GL_ALPHA; // GL_RED
+ theDataType = GL_UNSIGNED_BYTE;
+ return true;
}
default:
{
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 (!Create (theCtx))
+ {
+ Release (theCtx.operator->());
+ return false;
+ }
+ myHasMipmaps = Standard_False;
+ 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;
+#endif
+ const GLsizei aWidth = theSizeX;
+ const GLsizei aHeight = theSizeY;
const GLsizei aMaxSize = theCtx->MaxTextureSize();
- const GLsizei aWidth = (GLsizei )theImage.SizeX();
- const GLsizei aHeight = (GLsizei )theImage.SizeY();
// 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
+ // Trying to create NPOT textures 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 ? getPowerOfTwo (aWidth, aMaxSize) : Min (aWidth, aMaxSize);
- const GLsizei aHeightOut = toForceP2 ? getPowerOfTwo (aHeight, aMaxSize) : Min (aHeight, aMaxSize);
+ const GLsizei aWidthOut = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize) : Min (aWidth, aMaxSize);
+ const GLsizei aHeightOut = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize) : Min (aHeight, aMaxSize);
+#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;
+ 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
+ }
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // ensure alignment will not screw up the party
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, GL_LINEAR);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Image_PixMap aCopy;
- GLvoid* aDataPtr = (GLvoid* )theImage.Data();
- if (aWidth != aWidthOut)
+ if (aDataPtr != NULL)
{
- if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), 1)
- || gluScaleImage (aPixelFormat,
- aWidth, 1, aDataType, theImage.Data(),
- aWidthOut, 1, aDataType, aCopy.ChangeData()) != 0)
+ if (aWidth != aWidthOut)
{
- Unbind (theCtx);
- return false;
+ glPixelStorei (GL_PACK_ALIGNMENT, 1);
+ glPixelStorei (GL_PACK_ROW_LENGTH, 0);
+ if (!aCopy.InitTrash (theImage->Format(), Standard_Size(aWidthOut), 1)
+ || gluScaleImage (thePixelFormat,
+ aWidth, 1, theDataType, theImage->Data(),
+ aWidthOut, 1, theDataType, aCopy.ChangeData()) != 0)
+ {
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+
+ aDataPtr = (GLvoid* )aCopy.Data();
+ anUnpackSentry.Reset();
}
-
- aDataPtr = (GLvoid* )aCopy.Data();
}
// use proxy to check texture could be created or not
- glTexImage1D (GL_PROXY_TEXTURE_1D, 0, aTextureFormat,
+ glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
aWidthOut, 0,
- aPixelFormat, aDataType, NULL);
+ thePixelFormat, theDataType, NULL);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
if (aTestWidth == 0)
{
// no memory or broken input parameters
Unbind (theCtx);
+ Release (theCtx.operator->());
return false;
}
- glTexImage1D (GL_TEXTURE_1D, 0, aTextureFormat,
+ glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
aWidthOut, 0,
- aPixelFormat, aDataType, aDataPtr);
+ thePixelFormat, theDataType, aDataPtr);
+ if (glGetError() != GL_NO_ERROR)
+ {
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+
+ mySizeX = aWidthOut;
+ mySizeY = 1;
Unbind (theCtx);
return true;
+ #else
+ return false;
+ #endif
}
case Graphic3d_TOT_2D:
{
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Image_PixMap aCopy;
- GLvoid* aDataPtr = (GLvoid* )theImage.Data();
- if (aWidth != aWidthOut || aHeight != aHeightOut)
+ if (aDataPtr != NULL)
{
- // scale texture
-
- if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut))
- || gluScaleImage (aPixelFormat,
- aWidth, aHeight, aDataType, theImage.Data(),
- aWidthOut, aHeightOut, aDataType, aCopy.ChangeData()) != 0)
+ if (aWidth != aWidthOut || aHeight != aHeightOut)
{
+ #if !defined(GL_ES_VERSION_2_0)
+ // 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 (thePixelFormat,
+ aWidth, aHeight, theDataType, theImage->Data(),
+ aWidthOut, aHeightOut, theDataType, aCopy.ChangeData()) != 0)
+ {
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+
+ aDataPtr = (GLvoid* )aCopy.Data();
+ anUnpackSentry.Reset();
+ #else
Unbind (theCtx);
+ Release (theCtx.operator->());
return false;
+ #endif
}
-
- aDataPtr = (GLvoid* )aCopy.Data();
}
+ #if !defined(GL_ES_VERSION_2_0)
// use proxy to check texture could be created or not
- glTexImage2D (GL_PROXY_TEXTURE_2D, 0, aTextureFormat,
+ glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
aWidthOut, aHeightOut, 0,
- aPixelFormat, aDataType, NULL);
+ thePixelFormat, theDataType, 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)
{
// no memory or broken input parameters
Unbind (theCtx);
+ Release (theCtx.operator->());
return false;
}
+ #endif
- glTexImage2D (GL_TEXTURE_2D, 0, aTextureFormat,
+ glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
aWidthOut, aHeightOut, 0,
- aPixelFormat, aDataType, aDataPtr);
+ thePixelFormat, theDataType, aDataPtr);
+ if (glGetError() != GL_NO_ERROR)
+ {
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+
+ mySizeX = aWidthOut;
+ mySizeY = aHeightOut;
Unbind (theCtx);
return true;
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, aTextureFormat,
- aWidth, aHeight,
- aPixelFormat, aDataType, theImage.Data()) == 0;
- Unbind (theCtx);
- return isCreated;
+ if (theCtx->arbFBO != NULL
+ && aWidth == aWidthOut && aHeight == 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,
+ aWidthOut, aHeightOut, 0,
+ thePixelFormat, theDataType, 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)
+ {
+ // no memory or broken input parameters
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+ #endif
+
+ // upload main picture
+ glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
+ aWidthOut, aHeightOut, 0,
+ thePixelFormat, theDataType, theImage->Data());
+ if (glGetError() != GL_NO_ERROR)
+ {
+ Unbind (theCtx);
+ Release (theCtx.operator->());
+ return false;
+ }
+
+ mySizeX = aWidthOut;
+ mySizeY = aHeightOut;
+
+ // generate mipmaps
+ //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
+ theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
+
+ Unbind (theCtx);
+ return true;
+ }
+ else
+ {
+ #if !defined(GL_ES_VERSION_2_0)
+ bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, anIntFormat,
+ aWidth, aHeight,
+ thePixelFormat, theDataType, theImage->Data()) == 0;
+ if (isCreated)
+ {
+ glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &mySizeX);
+ glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &mySizeY);
+ }
+
+ Unbind (theCtx);
+ return isCreated;
+ #else
+ Unbind (theCtx);
+ return false;
+ #endif
+ }
}
default:
{
+ 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 : 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;
+
+ const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
+ const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
+
+ Bind (theCtx);
+
+ if (myParams->Filter() == Graphic3d_TOTF_NEAREST)
+ {
+ glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ }
+ else
+ {
+ glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+
+ const GLint anIntFormat = theFormat.Internal();
+ myTextFormat = theFormat.Format();
+
+ glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE,
+ 0,
+ anIntFormat,
+ aSizeX,
+ aSizeY,
+ 0,
+ theFormat.Format(),
+ 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);
+
+ if (aTestSizeX == 0 || aTestSizeY == 0)
+ {
+ Unbind (theCtx);
+ return false;
+ }
+
+ glTexImage2D (myTarget,
+ 0,
+ anIntFormat,
+ aSizeX,
+ aSizeY,
+ 0,
+ theFormat.Format(),
+ GL_FLOAT,
+ NULL);
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+ Unbind (theCtx);
+ return false;
+ }
+
+ mySizeX = aSizeX;
+ mySizeY = aSizeY;
+
+ Unbind (theCtx);
+ return true;
+#else
+ return false;
+#endif
+}