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 // =======================================================================
31 // function : OpenGl_Texture
33 // =======================================================================
34 OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
36 myTextureId (NO_TEXTURE),
37 myTarget (GL_TEXTURE_2D),
40 myTextFormat (GL_FLOAT),
41 myHasMipmaps (Standard_False),
44 if (myParams.IsNull())
46 myParams = new Graphic3d_TextureParams();
50 // =======================================================================
51 // function : ~OpenGl_Texture
53 // =======================================================================
54 OpenGl_Texture::~OpenGl_Texture()
59 // =======================================================================
60 // function : HasMipmaps
62 // =======================================================================
63 const Standard_Boolean OpenGl_Texture::HasMipmaps() const
68 // =======================================================================
69 // function : GetParams
71 // =======================================================================
72 const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
77 // =======================================================================
78 // function : SetParams
80 // =======================================================================
81 void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
86 // =======================================================================
89 // =======================================================================
90 bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
92 if (myTextureId == NO_TEXTURE)
94 glGenTextures (1, &myTextureId);
96 return myTextureId != NO_TEXTURE;
99 // =======================================================================
100 // function : Release
102 // =======================================================================
103 void OpenGl_Texture::Release (const OpenGl_Context* theGlCtx)
105 if (myTextureId == NO_TEXTURE)
110 // application can not handle this case by exception - this is bug in code
111 Standard_ASSERT_RETURN (theGlCtx != NULL,
112 "OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
114 glDeleteTextures (1, &myTextureId);
115 myTextureId = NO_TEXTURE;
116 mySizeX = mySizeY = 0;
119 // =======================================================================
122 // =======================================================================
123 void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
124 const GLenum theTextureUnit) const
126 if (theCtx->IsGlGreaterEqual (1, 3))
128 theCtx->core13->glActiveTexture (theTextureUnit);
130 glBindTexture (myTarget, myTextureId);
133 // =======================================================================
136 // =======================================================================
137 void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
138 const GLenum theTextureUnit) const
140 if (theCtx->IsGlGreaterEqual (1, 3))
142 theCtx->core13->glActiveTexture (theTextureUnit);
144 glBindTexture (myTarget, NO_TEXTURE);
147 // =======================================================================
150 // =======================================================================
151 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
152 const Image_PixMap& theImage,
153 const Graphic3d_TypeOfTexture theType)
155 myHasMipmaps = Standard_False;
156 if (theImage.IsEmpty() || !Create (theCtx))
161 myTextFormat = GL_RGBA8;
162 GLenum aPixelFormat = 0;
163 GLenum aDataType = 0;
164 switch (theImage.Format())
166 case Image_PixMap::ImgGrayF:
168 myTextFormat = GL_ALPHA8; // GL_R8, GL_R32F
169 aPixelFormat = GL_ALPHA; // GL_RED
170 aDataType = GL_FLOAT;
173 case Image_PixMap::ImgRGBAF:
175 myTextFormat = GL_RGBA8; // GL_RGBA32F
176 aPixelFormat = GL_RGBA;
177 aDataType = GL_FLOAT;
180 case Image_PixMap::ImgBGRAF:
182 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
186 myTextFormat = GL_RGBA8; // GL_RGBA32F
187 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
188 aDataType = GL_FLOAT;
191 case Image_PixMap::ImgRGBF:
193 myTextFormat = GL_RGB8; // GL_RGB32F
194 aPixelFormat = GL_RGB;
195 aDataType = GL_FLOAT;
198 case Image_PixMap::ImgBGRF:
200 myTextFormat = GL_RGB8; // GL_RGB32F
201 aPixelFormat = GL_BGR; // equals to GL_BGR_EXT
202 aDataType = GL_FLOAT;
205 case Image_PixMap::ImgRGBA:
207 myTextFormat = GL_RGBA8;
208 aPixelFormat = GL_RGBA;
209 aDataType = GL_UNSIGNED_BYTE;
212 case Image_PixMap::ImgBGRA:
214 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
218 myTextFormat = GL_RGBA8;
219 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
220 aDataType = GL_UNSIGNED_BYTE;
223 case Image_PixMap::ImgRGB32:
225 myTextFormat = GL_RGB8;
226 aPixelFormat = GL_RGBA;
227 aDataType = GL_UNSIGNED_BYTE;
230 case Image_PixMap::ImgBGR32:
232 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
236 myTextFormat = GL_RGB8;
237 aPixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
238 aDataType = GL_UNSIGNED_BYTE;
241 case Image_PixMap::ImgRGB:
243 myTextFormat = GL_RGB8;
244 aPixelFormat = GL_RGB;
245 aDataType = GL_UNSIGNED_BYTE;
248 case Image_PixMap::ImgBGR:
250 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
254 myTextFormat = GL_RGB8;
255 aPixelFormat = GL_BGR; // equals to GL_BGR_EXT
256 aDataType = GL_UNSIGNED_BYTE;
259 case Image_PixMap::ImgGray:
261 myTextFormat = GL_ALPHA8; // GL_R8
262 aPixelFormat = GL_ALPHA; // GL_RED
263 aDataType = GL_UNSIGNED_BYTE;
272 const GLsizei aMaxSize = theCtx->MaxTextureSize();
273 const GLsizei aWidth = (GLsizei )theImage.SizeX();
274 const GLsizei aHeight = (GLsizei )theImage.SizeY();
276 // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
277 // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
278 // Trying to create NPOT rextures on such hardware will not fail
279 // but driver will fall back into software rendering,
280 const bool toForceP2 = !theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW;
281 const GLsizei aWidthOut = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize) : Min (aWidth, aMaxSize);
282 const GLsizei aHeightOut = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize) : Min (aHeight, aMaxSize);
284 GLint aTestWidth = 0;
285 GLint aTestHeight = 0;
287 glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // ensure alignment will not screw up the party
290 case Graphic3d_TOT_1D:
292 myTarget = GL_TEXTURE_1D;
294 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
295 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
298 GLvoid* aDataPtr = (GLvoid* )theImage.Data();
299 if (aWidth != aWidthOut)
301 if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), 1)
302 || gluScaleImage (aPixelFormat,
303 aWidth, 1, aDataType, theImage.Data(),
304 aWidthOut, 1, aDataType, aCopy.ChangeData()) != 0)
310 aDataPtr = (GLvoid* )aCopy.Data();
313 // use proxy to check texture could be created or not
314 glTexImage1D (GL_PROXY_TEXTURE_1D, 0, myTextFormat,
316 aPixelFormat, aDataType, NULL);
317 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
320 // no memory or broken input parameters
325 glTexImage1D (GL_TEXTURE_1D, 0, myTextFormat,
327 aPixelFormat, aDataType, aDataPtr);
328 if (glGetError() != GL_NO_ERROR)
340 case Graphic3d_TOT_2D:
342 myTarget = GL_TEXTURE_2D;
344 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
345 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
348 GLvoid* aDataPtr = (GLvoid* )theImage.Data();
349 if (aWidth != aWidthOut || aHeight != aHeightOut)
352 if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut))
353 || gluScaleImage (aPixelFormat,
354 aWidth, aHeight, aDataType, theImage.Data(),
355 aWidthOut, aHeightOut, aDataType, aCopy.ChangeData()) != 0)
361 aDataPtr = (GLvoid* )aCopy.Data();
364 // use proxy to check texture could be created or not
365 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, myTextFormat,
366 aWidthOut, aHeightOut, 0,
367 aPixelFormat, aDataType, NULL);
368 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
369 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
370 if (aTestWidth == 0 || aTestHeight == 0)
372 // no memory or broken input parameters
377 glTexImage2D (GL_TEXTURE_2D, 0, myTextFormat,
378 aWidthOut, aHeightOut, 0,
379 aPixelFormat, aDataType, aDataPtr);
380 if (glGetError() != GL_NO_ERROR)
387 mySizeY = aHeightOut;
392 case Graphic3d_TOT_2D_MIPMAP:
394 myTarget = GL_TEXTURE_2D;
395 myHasMipmaps = Standard_True;
397 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
398 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
400 if (theCtx->extFBO != NULL
401 && aWidth == aWidthOut && aHeight == aHeightOut)
403 // use proxy to check texture could be created or not
404 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, myTextFormat,
405 aWidthOut, aHeightOut, 0,
406 aPixelFormat, aDataType, NULL);
407 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
408 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
409 if (aTestWidth == 0 || aTestHeight == 0)
411 // no memory or broken input parameters
416 // upload main picture
417 glTexImage2D (GL_TEXTURE_2D, 0, myTextFormat,
418 aWidthOut, aHeightOut, 0,
419 aPixelFormat, aDataType, theImage.Data());
420 if (glGetError() != GL_NO_ERROR)
427 mySizeY = aHeightOut;
430 //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
431 theCtx->extFBO->glGenerateMipmapEXT (GL_TEXTURE_2D);
438 bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, myTextFormat,
440 aPixelFormat, aDataType, theImage.Data()) == 0;
443 glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &mySizeX);
444 glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &mySizeY);