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_ExtFBO.hxx>
22 #include <OpenGl_Context.hxx>
23 #include <Graphic3d_TextureParams.hxx>
24 #include <Standard_Assert.hxx>
25 #include <Image_PixMap.hxx>
27 IMPLEMENT_STANDARD_HANDLE (OpenGl_Texture, OpenGl_Resource)
28 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_Resource)
30 //! Function for getting power of to number larger or equal to input number.
31 //! @param theNumber number to 'power of two'
32 //! @param theThreshold upper threshold
33 //! @return power of two number
34 inline GLsizei getPowerOfTwo (const GLsizei theNumber,
35 const GLsizei theThreshold)
37 for (GLsizei p2 = 2; p2 <= theThreshold; p2 <<= 1)
47 // =======================================================================
48 // function : OpenGl_Texture
50 // =======================================================================
51 OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
53 myTextureId (NO_TEXTURE),
54 myTarget (GL_TEXTURE_2D),
57 myTextFormat (GL_FLOAT),
58 myHasMipmaps (Standard_False),
61 if (myParams.IsNull())
63 myParams = new Graphic3d_TextureParams();
67 // =======================================================================
68 // function : ~OpenGl_Texture
70 // =======================================================================
71 OpenGl_Texture::~OpenGl_Texture()
76 // =======================================================================
77 // function : HasMipmaps
79 // =======================================================================
80 const Standard_Boolean OpenGl_Texture::HasMipmaps() const
85 // =======================================================================
86 // function : GetParams
88 // =======================================================================
89 const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
94 // =======================================================================
95 // function : SetParams
97 // =======================================================================
98 void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
100 myParams = theParams;
103 // =======================================================================
106 // =======================================================================
107 bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
109 if (myTextureId == NO_TEXTURE)
111 glGenTextures (1, &myTextureId);
113 return myTextureId != NO_TEXTURE;
116 // =======================================================================
117 // function : Release
119 // =======================================================================
120 void OpenGl_Texture::Release (const OpenGl_Context* theGlCtx)
122 if (myTextureId == NO_TEXTURE)
127 // application can not handle this case by exception - this is bug in code
128 Standard_ASSERT_RETURN (theGlCtx != NULL,
129 "OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
131 glDeleteTextures (1, &myTextureId);
132 myTextureId = NO_TEXTURE;
133 mySizeX = mySizeY = 0;
136 // =======================================================================
139 // =======================================================================
140 void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
141 const GLenum theTextureUnit) const
143 if (theCtx->IsGlGreaterEqual (1, 3))
145 theCtx->core13->glActiveTexture (theTextureUnit);
147 glBindTexture (myTarget, myTextureId);
150 // =======================================================================
153 // =======================================================================
154 void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
155 const GLenum theTextureUnit) const
157 if (theCtx->IsGlGreaterEqual (1, 3))
159 theCtx->core13->glActiveTexture (theTextureUnit);
161 glBindTexture (myTarget, NO_TEXTURE);
164 // =======================================================================
167 // =======================================================================
168 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
169 const Image_PixMap& theImage,
170 const Graphic3d_TypeOfTexture theType)
172 myHasMipmaps = Standard_False;
173 if (theImage.IsEmpty() || !Create (theCtx))
178 GLenum aTextureFormat = GL_RGBA8;
179 GLenum aPixelFormat = 0;
180 GLenum aDataType = 0;
181 switch (theImage.Format())
183 case Image_PixMap::ImgGrayF:
185 aTextureFormat = GL_ALPHA8; // GL_R8, GL_R32F
186 aPixelFormat = GL_ALPHA; // GL_RED
187 aDataType = GL_FLOAT;
190 case Image_PixMap::ImgRGBAF:
192 aTextureFormat = GL_RGBA8; // GL_RGBA32F
193 aPixelFormat = GL_RGBA;
194 aDataType = GL_FLOAT;
197 case Image_PixMap::ImgBGRAF:
199 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
203 aTextureFormat = GL_RGBA8; // GL_RGBA32F
204 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
205 aDataType = GL_FLOAT;
208 case Image_PixMap::ImgRGBF:
210 aTextureFormat = GL_RGB8; // GL_RGB32F
211 aPixelFormat = GL_RGB;
212 aDataType = GL_FLOAT;
215 case Image_PixMap::ImgBGRF:
217 aTextureFormat = GL_RGB8; // GL_RGB32F
218 aPixelFormat = GL_BGR; // equals to GL_BGR_EXT
219 aDataType = GL_FLOAT;
222 case Image_PixMap::ImgRGBA:
224 aTextureFormat = GL_RGBA8;
225 aPixelFormat = GL_RGBA;
226 aDataType = GL_UNSIGNED_BYTE;
229 case Image_PixMap::ImgBGRA:
231 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
235 aTextureFormat = GL_RGBA8;
236 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
237 aDataType = GL_UNSIGNED_BYTE;
240 case Image_PixMap::ImgRGB32:
242 aTextureFormat = GL_RGB8;
243 aPixelFormat = GL_RGBA;
244 aDataType = GL_UNSIGNED_BYTE;
247 case Image_PixMap::ImgBGR32:
249 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
253 aTextureFormat = GL_RGB8;
254 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
255 aDataType = GL_UNSIGNED_BYTE;
258 case Image_PixMap::ImgRGB:
260 aTextureFormat = GL_RGB8;
261 aPixelFormat = GL_RGB;
262 aDataType = GL_UNSIGNED_BYTE;
265 case Image_PixMap::ImgBGR:
267 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
271 aTextureFormat = GL_RGB8;
272 aPixelFormat = GL_BGR; // equals to GL_BGR_EXT
273 aDataType = GL_UNSIGNED_BYTE;
276 case Image_PixMap::ImgGray:
278 aTextureFormat = GL_ALPHA8; // GL_R8
279 aPixelFormat = GL_ALPHA; // GL_RED
280 aDataType = GL_UNSIGNED_BYTE;
289 const GLsizei aMaxSize = theCtx->MaxTextureSize();
290 const GLsizei aWidth = (GLsizei )theImage.SizeX();
291 const GLsizei aHeight = (GLsizei )theImage.SizeY();
293 // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
294 // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
295 // Trying to create NPOT rextures on such hardware will not fail
296 // but driver will fall back into software rendering,
297 const bool toForceP2 = !theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW;
298 const GLsizei aWidthOut = toForceP2 ? getPowerOfTwo (aWidth, aMaxSize) : Min (aWidth, aMaxSize);
299 const GLsizei aHeightOut = toForceP2 ? getPowerOfTwo (aHeight, aMaxSize) : Min (aHeight, aMaxSize);
301 GLint aTestWidth = 0;
302 GLint aTestHeight = 0;
304 glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // ensure alignment will not screw up the party
307 case Graphic3d_TOT_1D:
309 myTarget = GL_TEXTURE_1D;
311 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
312 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
315 GLvoid* aDataPtr = (GLvoid* )theImage.Data();
316 if (aWidth != aWidthOut)
318 if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), 1)
319 || gluScaleImage (aPixelFormat,
320 aWidth, 1, aDataType, theImage.Data(),
321 aWidthOut, 1, aDataType, aCopy.ChangeData()) != 0)
327 aDataPtr = (GLvoid* )aCopy.Data();
330 // use proxy to check texture could be created or not
331 glTexImage1D (GL_PROXY_TEXTURE_1D, 0, aTextureFormat,
333 aPixelFormat, aDataType, NULL);
334 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
337 // no memory or broken input parameters
342 glTexImage1D (GL_TEXTURE_1D, 0, aTextureFormat,
344 aPixelFormat, aDataType, aDataPtr);
349 case Graphic3d_TOT_2D:
351 myTarget = GL_TEXTURE_2D;
353 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
354 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
357 GLvoid* aDataPtr = (GLvoid* )theImage.Data();
358 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 if (theCtx->extFBO != NULL
402 && aWidth == aWidthOut && aHeight == aHeightOut)
404 // use proxy to check texture could be created or not
405 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, aTextureFormat,
406 aWidthOut, aHeightOut, 0,
407 aPixelFormat, aDataType, NULL);
408 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
409 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
410 if (aTestWidth == 0 || aTestHeight == 0)
412 // no memory or broken input parameters
417 // upload main picture
418 glTexImage2D (GL_TEXTURE_2D, 0, aTextureFormat,
419 aWidthOut, aHeightOut, 0,
420 aPixelFormat, aDataType, theImage.Data());
423 //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
424 theCtx->extFBO->glGenerateMipmapEXT (GL_TEXTURE_2D);
431 bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, aTextureFormat,
433 aPixelFormat, aDataType, theImage.Data()) == 0;