1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
19 #include <OpenGl_Texture.hxx>
21 #include <OpenGl_Context.hxx>
22 #include <Graphic3d_TextureParams.hxx>
23 #include <Standard_Assert.hxx>
24 #include <Image_PixMap.hxx>
26 IMPLEMENT_STANDARD_HANDLE (OpenGl_Texture, OpenGl_Resource)
27 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_Resource)
29 //! Function for getting power of to number larger or equal to input number.
30 //! @param theNumber number to 'power of two'
31 //! @param theThreshold upper threshold
32 //! @return power of two number
33 inline GLsizei getPowerOfTwo (const GLsizei theNumber,
34 const GLsizei theThreshold)
36 for (GLsizei p2 = 2; p2 <= theThreshold; p2 <<= 1)
46 // =======================================================================
47 // function : OpenGl_Texture
49 // =======================================================================
50 OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
52 myTextureId (NO_TEXTURE),
53 myTarget (GL_TEXTURE_2D),
56 myTextFormat (GL_FLOAT),
57 myHasMipmaps (Standard_False),
60 if (myParams.IsNull())
62 myParams = new Graphic3d_TextureParams();
66 // =======================================================================
67 // function : ~OpenGl_Texture
69 // =======================================================================
70 OpenGl_Texture::~OpenGl_Texture()
75 // =======================================================================
76 // function : HasMipmaps
78 // =======================================================================
79 const Standard_Boolean OpenGl_Texture::HasMipmaps() const
84 // =======================================================================
85 // function : GetParams
87 // =======================================================================
88 const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
93 // =======================================================================
94 // function : SetParams
96 // =======================================================================
97 void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
102 // =======================================================================
105 // =======================================================================
106 bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
108 if (myTextureId == NO_TEXTURE)
110 glGenTextures (1, &myTextureId);
112 return myTextureId != NO_TEXTURE;
115 // =======================================================================
116 // function : Release
118 // =======================================================================
119 void OpenGl_Texture::Release (const OpenGl_Context* theGlCtx)
121 if (myTextureId == NO_TEXTURE)
126 // application can not handle this case by exception - this is bug in code
127 Standard_ASSERT_RETURN (theGlCtx != NULL,
128 "OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
130 glDeleteTextures (1, &myTextureId);
131 myTextureId = NO_TEXTURE;
132 mySizeX = mySizeY = 0;
135 // =======================================================================
138 // =======================================================================
139 void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
140 const GLenum theTextureUnit) const
142 if (theCtx->IsGlGreaterEqual (1, 3))
144 theCtx->core13->glActiveTexture (theTextureUnit);
146 glBindTexture (myTarget, myTextureId);
149 // =======================================================================
152 // =======================================================================
153 void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
154 const GLenum theTextureUnit) const
156 if (theCtx->IsGlGreaterEqual (1, 3))
158 theCtx->core13->glActiveTexture (theTextureUnit);
160 glBindTexture (myTarget, NO_TEXTURE);
163 // =======================================================================
166 // =======================================================================
167 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
168 const Image_PixMap& theImage,
169 const Graphic3d_TypeOfTexture theType)
171 myHasMipmaps = Standard_False;
172 if (theImage.IsEmpty() || !Create (theCtx))
177 GLenum aTextureFormat = GL_RGBA8;
178 GLenum aPixelFormat = 0;
179 GLenum aDataType = 0;
180 switch (theImage.Format())
182 case Image_PixMap::ImgGrayF:
184 aTextureFormat = GL_ALPHA8; // GL_R8, GL_R32F
185 aPixelFormat = GL_ALPHA; // GL_RED
186 aDataType = GL_FLOAT;
189 case Image_PixMap::ImgRGBAF:
191 aTextureFormat = GL_RGBA8; // GL_RGBA32F
192 aPixelFormat = GL_RGBA;
193 aDataType = GL_FLOAT;
196 case Image_PixMap::ImgBGRAF:
198 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
202 aTextureFormat = GL_RGBA8; // GL_RGBA32F
203 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
204 aDataType = GL_FLOAT;
207 case Image_PixMap::ImgRGBF:
209 aTextureFormat = GL_RGB8; // GL_RGB32F
210 aPixelFormat = GL_RGB;
211 aDataType = GL_FLOAT;
214 case Image_PixMap::ImgBGRF:
216 aTextureFormat = GL_RGB8; // GL_RGB32F
217 aPixelFormat = GL_BGR; // equals to GL_BGR_EXT
218 aDataType = GL_FLOAT;
221 case Image_PixMap::ImgRGBA:
223 aTextureFormat = GL_RGBA8;
224 aPixelFormat = GL_RGBA;
225 aDataType = GL_UNSIGNED_BYTE;
228 case Image_PixMap::ImgBGRA:
230 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
234 aTextureFormat = GL_RGBA8;
235 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
236 aDataType = GL_UNSIGNED_BYTE;
239 case Image_PixMap::ImgRGB32:
241 aTextureFormat = GL_RGB8;
242 aPixelFormat = GL_RGBA;
243 aDataType = GL_UNSIGNED_BYTE;
246 case Image_PixMap::ImgBGR32:
248 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
252 aTextureFormat = GL_RGB8;
253 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
254 aDataType = GL_UNSIGNED_BYTE;
257 case Image_PixMap::ImgRGB:
259 aTextureFormat = GL_RGB8;
260 aPixelFormat = GL_RGB;
261 aDataType = GL_UNSIGNED_BYTE;
264 case Image_PixMap::ImgBGR:
266 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
270 aTextureFormat = GL_RGB8;
271 aPixelFormat = GL_BGR; // equals to GL_BGR_EXT
272 aDataType = GL_UNSIGNED_BYTE;
275 case Image_PixMap::ImgGray:
277 aTextureFormat = GL_ALPHA8; // GL_R8
278 aPixelFormat = GL_ALPHA; // GL_RED
279 aDataType = GL_UNSIGNED_BYTE;
288 const GLsizei aMaxSize = theCtx->MaxTextureSize();
289 const GLsizei aWidth = (GLsizei )theImage.SizeX();
290 const GLsizei aHeight = (GLsizei )theImage.SizeY();
292 // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
293 // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
294 // Trying to create NPOT rextures on such hardware will not fail
295 // but driver will fall back into software rendering,
296 const bool toForceP2 = !theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW;
297 const GLsizei aWidthOut = toForceP2 ? getPowerOfTwo (aWidth, aMaxSize) : Min (aWidth, aMaxSize);
298 const GLsizei aHeightOut = toForceP2 ? getPowerOfTwo (aHeight, aMaxSize) : Min (aHeight, aMaxSize);
300 GLint aTestWidth = 0;
301 GLint aTestHeight = 0;
303 glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // ensure alignment will not screw up the party
306 case Graphic3d_TOT_1D:
308 myTarget = GL_TEXTURE_1D;
310 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
311 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
314 GLvoid* aDataPtr = (GLvoid* )theImage.Data();
315 if (aWidth != aWidthOut)
317 if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), 1)
318 || gluScaleImage (aPixelFormat,
319 aWidth, 1, aDataType, theImage.Data(),
320 aWidthOut, 1, aDataType, aCopy.ChangeData()) != 0)
326 aDataPtr = (GLvoid* )aCopy.Data();
329 // use proxy to check texture could be created or not
330 glTexImage1D (GL_PROXY_TEXTURE_1D, 0, aTextureFormat,
332 aPixelFormat, aDataType, NULL);
333 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
336 // no memory or broken input parameters
341 glTexImage1D (GL_TEXTURE_1D, 0, aTextureFormat,
343 aPixelFormat, aDataType, aDataPtr);
348 case Graphic3d_TOT_2D:
350 myTarget = GL_TEXTURE_2D;
352 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
353 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
356 GLvoid* aDataPtr = (GLvoid* )theImage.Data();
357 if (aWidth != aWidthOut || aHeight != aHeightOut)
361 if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut))
362 || gluScaleImage (aPixelFormat,
363 aWidth, aHeight, aDataType, theImage.Data(),
364 aWidthOut, aHeightOut, aDataType, aCopy.ChangeData()) != 0)
370 aDataPtr = (GLvoid* )aCopy.Data();
373 // use proxy to check texture could be created or not
374 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, aTextureFormat,
375 aWidthOut, aHeightOut, 0,
376 aPixelFormat, aDataType, NULL);
377 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
378 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
379 if (aTestWidth == 0 || aTestHeight == 0)
381 // no memory or broken input parameters
386 glTexImage2D (GL_TEXTURE_2D, 0, aTextureFormat,
387 aWidthOut, aHeightOut, 0,
388 aPixelFormat, aDataType, aDataPtr);
393 case Graphic3d_TOT_2D_MIPMAP:
395 myTarget = GL_TEXTURE_2D;
396 myHasMipmaps = Standard_True;
398 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
399 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
401 bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, aTextureFormat,
403 aPixelFormat, aDataType, theImage.Data()) == 0;