0027670: Visualization - avoid duplication of structures defining primitive array...
[occt.git] / src / OpenGl / OpenGl_Texture.cxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2013-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <OpenGl_Texture.hxx>
16
17 #include <OpenGl_ArbFBO.hxx>
18 #include <OpenGl_Context.hxx>
19 #include <OpenGl_GlCore32.hxx>
20 #include <Graphic3d_TextureParams.hxx>
21 #include <TCollection_ExtendedString.hxx>
22 #include <Standard_Assert.hxx>
23 #include <Image_PixMap.hxx>
24
25
26 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture,OpenGl_Resource)
27
28 //! Simple class to reset unpack alignment settings
29 struct OpenGl_UnpackAlignmentSentry
30 {
31
32   //! Reset unpack alignment settings to safe values
33   void Reset()
34   {
35     glPixelStorei (GL_UNPACK_ALIGNMENT,  1);
36   #if !defined(GL_ES_VERSION_2_0)
37     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
38   #endif
39   }
40
41   ~OpenGl_UnpackAlignmentSentry()
42   {
43     Reset();
44   }
45
46 };
47
48 // =======================================================================
49 // function : OpenGl_Texture
50 // purpose  :
51 // =======================================================================
52 OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
53 : OpenGl_Resource(),
54   myTextureId (NO_TEXTURE),
55   myTarget (GL_TEXTURE_2D),
56   mySizeX (0),
57   mySizeY (0),
58   mySizeZ (0),
59   myTextFormat (GL_RGBA),
60   myHasMipmaps (Standard_False),
61   myIsAlpha    (false),
62   myParams     (theParams)
63 {
64   if (myParams.IsNull())
65   {
66     myParams = new Graphic3d_TextureParams();
67   }
68 }
69
70 // =======================================================================
71 // function : ~OpenGl_Texture
72 // purpose  :
73 // =======================================================================
74 OpenGl_Texture::~OpenGl_Texture()
75 {
76   Release (NULL);
77 }
78
79 // =======================================================================
80 // function : HasMipmaps
81 // purpose  :
82 // =======================================================================
83 Standard_Boolean OpenGl_Texture::HasMipmaps() const
84 {
85   return myHasMipmaps;
86 }
87
88 // =======================================================================
89 // function : GetParams
90 // purpose  :
91 // =======================================================================
92 const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
93 {
94   return myParams;
95 }
96
97 // =======================================================================
98 // function : SetParams
99 // purpose  :
100 // =======================================================================
101 void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
102 {
103   myParams = theParams;
104 }
105
106 // =======================================================================
107 // function : Create
108 // purpose  :
109 // =======================================================================
110 bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
111 {
112   if (myTextureId == NO_TEXTURE)
113   {
114     glGenTextures (1, &myTextureId);
115   }
116   return myTextureId != NO_TEXTURE;
117 }
118
119 // =======================================================================
120 // function : Release
121 // purpose  :
122 // =======================================================================
123 void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
124 {
125   if (myTextureId == NO_TEXTURE)
126   {
127     return;
128   }
129
130   // application can not handle this case by exception - this is bug in code
131   Standard_ASSERT_RETURN (theGlCtx != NULL,
132     "OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
133
134   if (theGlCtx->IsValid())
135   {
136     glDeleteTextures (1, &myTextureId);
137   }
138   myTextureId = NO_TEXTURE;
139   mySizeX = mySizeY = 0;
140 }
141
142 // =======================================================================
143 // function : Bind
144 // purpose  :
145 // =======================================================================
146 void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
147                            const GLenum theTextureUnit) const
148 {
149   if (theCtx->core15fwd != NULL)
150   {
151     theCtx->core15fwd->glActiveTexture (theTextureUnit);
152   }
153   glBindTexture (myTarget, myTextureId);
154 }
155
156 // =======================================================================
157 // function : Unbind
158 // purpose  :
159 // =======================================================================
160 void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
161                              const GLenum theTextureUnit) const
162 {
163   if (theCtx->core15fwd != NULL)
164   {
165     theCtx->core15fwd->glActiveTexture (theTextureUnit);
166   }
167   glBindTexture (myTarget, NO_TEXTURE);
168 }
169
170 //=======================================================================
171 //function : GetDataFormat
172 //purpose  :
173 //=======================================================================
174 bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
175                                     const Image_PixMap&           theData,
176                                     GLint&                        theTextFormat,
177                                     GLenum&                       thePixelFormat,
178                                     GLenum&                       theDataType)
179 {
180   theTextFormat  = GL_RGBA8;
181   thePixelFormat = 0;
182   theDataType    = 0;
183   switch (theData.Format())
184   {
185     case Image_PixMap::ImgGrayF:
186     {
187       if (theCtx->core11 == NULL)
188       {
189         theTextFormat  = GL_R8;  // GL_R32F
190         thePixelFormat = GL_RED;
191       }
192       else
193       {
194         theTextFormat  = GL_LUMINANCE8;
195         thePixelFormat = GL_LUMINANCE;
196       }
197       theDataType = GL_FLOAT;
198       return true;
199     }
200     case Image_PixMap::ImgAlphaF:
201     {
202       if (theCtx->core11 == NULL)
203       {
204         theTextFormat  = GL_R8;  // GL_R32F
205         thePixelFormat = GL_RED;
206       }
207       else
208       {
209         theTextFormat  = GL_ALPHA8;
210         thePixelFormat = GL_ALPHA;
211       }
212       theDataType = GL_FLOAT;
213       return true;
214     }
215     case Image_PixMap::ImgRGBAF:
216     {
217       theTextFormat  = GL_RGBA8; // GL_RGBA32F
218       thePixelFormat = GL_RGBA;
219       theDataType    = GL_FLOAT;
220       return true;
221     }
222     case Image_PixMap::ImgBGRAF:
223     {
224       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
225       {
226         return false;
227       }
228       theTextFormat  = GL_RGBA8;    // GL_RGBA32F
229       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
230       theDataType    = GL_FLOAT;
231       return true;
232     }
233     case Image_PixMap::ImgRGBF:
234     {
235       theTextFormat  = GL_RGB8; // GL_RGB32F
236       thePixelFormat = GL_RGB;
237       theDataType    = GL_FLOAT;
238       return true;
239     }
240     case Image_PixMap::ImgBGRF:
241     {
242     #if !defined(GL_ES_VERSION_2_0)
243       theTextFormat  = GL_RGB8; // GL_RGB32F
244       thePixelFormat = GL_BGR;  // equals to GL_BGR_EXT
245       theDataType    = GL_FLOAT;
246       return true;
247     #else
248       return false;
249     #endif
250     }
251     case Image_PixMap::ImgRGBA:
252     {
253       theTextFormat = GL_RGBA8;
254       thePixelFormat = GL_RGBA;
255       theDataType    = GL_UNSIGNED_BYTE;
256       return true;
257     }
258     case Image_PixMap::ImgBGRA:
259     {
260       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
261       {
262         return false;
263       }
264       theTextFormat  = GL_RGBA8;
265       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
266       theDataType    = GL_UNSIGNED_BYTE;
267       return true;
268     }
269     case Image_PixMap::ImgRGB32:
270     {
271       theTextFormat = GL_RGB8;
272       thePixelFormat = GL_RGBA;
273       theDataType    = GL_UNSIGNED_BYTE;
274       return true;
275     }
276     case Image_PixMap::ImgBGR32:
277     {
278       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
279       {
280         return false;
281       }
282       theTextFormat  = GL_RGB8;
283       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
284       theDataType    = GL_UNSIGNED_BYTE;
285       return true;
286     }
287     case Image_PixMap::ImgRGB:
288     {
289       theTextFormat = GL_RGB8;
290       thePixelFormat = GL_RGB;
291       theDataType    = GL_UNSIGNED_BYTE;
292       return true;
293     }
294     case Image_PixMap::ImgBGR:
295     {
296     #if !defined(GL_ES_VERSION_2_0)
297       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
298       {
299         return false;
300       }
301       theTextFormat = GL_RGB8;
302       thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
303       theDataType    = GL_UNSIGNED_BYTE;
304       return true;
305     #else
306       return false;
307     #endif
308     }
309     case Image_PixMap::ImgGray:
310     {
311       if (theCtx->core11 == NULL)
312       {
313         theTextFormat  = GL_R8;
314         thePixelFormat = GL_RED;
315       }
316       else
317       {
318         theTextFormat  = GL_LUMINANCE8;
319         thePixelFormat = GL_LUMINANCE;
320       }
321       theDataType = GL_UNSIGNED_BYTE;
322       return true;
323     }
324     case Image_PixMap::ImgAlpha:
325     {
326       if (theCtx->core11 == NULL)
327       {
328         theTextFormat  = GL_R8;
329         thePixelFormat = GL_RED;
330       }
331       else
332       {
333         theTextFormat  = GL_ALPHA8;
334         thePixelFormat = GL_ALPHA;
335       }
336       theDataType = GL_UNSIGNED_BYTE;
337       return true;
338     }
339     case Image_PixMap::ImgUNKNOWN:
340     {
341       return false;
342     }
343   }
344   return false;
345 }
346
347 // =======================================================================
348 // function : Init
349 // purpose  :
350 // =======================================================================
351 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
352                            const Standard_Integer        theTextFormat,
353                            const GLenum                  thePixelFormat,
354                            const GLenum                  theDataType,
355                            const Standard_Integer        theSizeX,
356                            const Standard_Integer        theSizeY,
357                            const Graphic3d_TypeOfTexture theType,
358                            const Image_PixMap*           theImage)
359 {
360   if (!Create (theCtx))
361   {
362     Release (theCtx.operator->());
363     return false;
364   }
365
366   if (theImage != NULL)
367   {
368     myIsAlpha = theImage->Format() == Image_PixMap::ImgAlpha
369              || theImage->Format() == Image_PixMap::ImgAlphaF;
370   }
371   else
372   {
373     myIsAlpha = thePixelFormat == GL_ALPHA;
374   }
375
376   myHasMipmaps             = Standard_False;
377   myTextFormat             = thePixelFormat;
378 #if !defined(GL_ES_VERSION_2_0)
379   const GLint anIntFormat  = theTextFormat;
380 #else
381   // ES does not support sized formats and format conversions - them detected from data type
382   const GLint anIntFormat  = thePixelFormat;
383   (void) theTextFormat;
384 #endif
385   const GLsizei aWidth     = theSizeX;
386   const GLsizei aHeight    = theSizeY;
387   const GLsizei aMaxSize   = theCtx->MaxTextureSize();
388
389   if (aWidth > aMaxSize || aHeight > aMaxSize)
390   {
391     TCollection_ExtendedString aWarnMessage = TCollection_ExtendedString ("Error: Texture dimension - ")
392       + aWidth + "x" + aHeight + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")";
393
394     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
395     Release (theCtx.operator->());
396     return false;
397   }
398 #if !defined(GL_ES_VERSION_2_0)
399   else if (!theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW)
400   {
401     // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
402     // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
403     // Trying to create NPOT textures on such hardware will not fail
404     // but driver will fall back into software rendering,
405     const GLsizei aWidthP2  = OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize);
406     const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize);
407
408     if (aWidth != aWidthP2 || (theType != Graphic3d_TOT_1D && aHeight != aHeightP2))
409     {
410       TCollection_ExtendedString aWarnMessage =
411         TCollection_ExtendedString ("Error: NPOT Textures (") + aWidth + "x" + aHeight + ") are not supported by hardware.";
412
413       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
414
415       Release (theCtx.operator->());
416       return false;
417     }
418   }
419 #else
420   else if (!theCtx->IsGlGreaterEqual (3, 0) && theType == Graphic3d_TOT_2D_MIPMAP)
421   {
422     // Mipmap NPOT textures are not supported by OpenGL ES 2.0.
423     const GLsizei aWidthP2  = OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize);
424     const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize);
425
426     if (aWidth != aWidthP2 || aHeight != aHeightP2)
427     {
428       TCollection_ExtendedString aWarnMessage =
429         TCollection_ExtendedString ("Error: Mipmap NPOT Textures (") + aWidth + "x" + aHeight + ") are not supported by OpenGL ES 2.0";
430
431       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
432
433       Release (theCtx.operator->());
434       return false;
435     }
436   }
437 #endif
438
439   const GLenum  aFilter   = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
440   const GLenum  aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
441
442 #if !defined(GL_ES_VERSION_2_0)
443   GLint aTestWidth  = 0;
444   GLint aTestHeight = 0;
445 #endif
446   GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
447
448   // setup the alignment
449   OpenGl_UnpackAlignmentSentry anUnpackSentry;
450   (void)anUnpackSentry; // avoid compiler warning
451
452   if (aDataPtr != NULL)
453   {
454     const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
455     glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
456
457   #if !defined(GL_ES_VERSION_2_0)
458     // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
459     const GLint anExtraBytes = GLint(theImage->RowExtraBytes());
460     const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes());
461     glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
462   #endif
463   }
464
465   switch (theType)
466   {
467     case Graphic3d_TOT_1D:
468     {
469     #if !defined(GL_ES_VERSION_2_0)
470       myTarget = GL_TEXTURE_1D;
471       Bind (theCtx);
472       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
473       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
474       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
475
476       // use proxy to check texture could be created or not
477       glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
478                     aWidth, 0,
479                     thePixelFormat, theDataType, NULL);
480       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
481       if (aTestWidth == 0)
482       {
483         // no memory or broken input parameters
484         Unbind (theCtx);
485         Release (theCtx.operator->());
486         return false;
487       }
488
489       glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
490                     aWidth, 0,
491                     thePixelFormat, theDataType, aDataPtr);
492       if (glGetError() != GL_NO_ERROR)
493       {
494         Unbind (theCtx);
495         Release (theCtx.operator->());
496         return false;
497       }
498
499       mySizeX = aWidth;
500       mySizeY = 1;
501
502       Unbind (theCtx);
503       return true;
504     #else
505       Release (theCtx.operator->());
506       return false;
507     #endif
508     }
509     case Graphic3d_TOT_2D:
510     {
511       myTarget = GL_TEXTURE_2D;
512       Bind (theCtx);
513       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilter);
514       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
515       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
516       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
517
518     #if !defined(GL_ES_VERSION_2_0)
519       // use proxy to check texture could be created or not
520       glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
521                     aWidth, aHeight, 0,
522                     thePixelFormat, theDataType, NULL);
523       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &aTestWidth);
524       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
525       if (aTestWidth == 0 || aTestHeight == 0)
526       {
527         // no memory or broken input parameters
528         Unbind (theCtx);
529         Release (theCtx.operator->());
530         return false;
531       }
532     #endif
533
534       glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
535                     aWidth, aHeight, 0,
536                     thePixelFormat, theDataType, aDataPtr);
537       if (glGetError() != GL_NO_ERROR)
538       {
539         Unbind (theCtx);
540         Release (theCtx.operator->());
541         return false;
542       }
543
544       mySizeX = aWidth;
545       mySizeY = aHeight;
546
547       Unbind (theCtx);
548       return true;
549     }
550     case Graphic3d_TOT_2D_MIPMAP:
551     {
552       myTarget     = GL_TEXTURE_2D;
553       myHasMipmaps = Standard_True;
554
555       GLenum aFilterMin = aFilter;
556       aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
557       if (myParams->Filter() == Graphic3d_TOTF_BILINEAR)
558       {
559         aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
560       }
561       else if (myParams->Filter() == Graphic3d_TOTF_TRILINEAR)
562       {
563         aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
564       }
565
566       Bind (theCtx);
567       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
568       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
569       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
570       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
571
572     #if !defined(GL_ES_VERSION_2_0)
573       // use proxy to check texture could be created or not
574       glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
575                     aWidth, aHeight, 0,
576                     thePixelFormat, theDataType, NULL);
577       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &aTestWidth);
578       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
579       if (aTestWidth == 0 || aTestHeight == 0)
580       {
581         // no memory or broken input parameters
582         Unbind (theCtx);
583         Release (theCtx.operator->());
584         return false;
585       }
586     #endif
587
588       // upload main picture
589       glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
590                     aWidth, aHeight, 0,
591                     thePixelFormat, theDataType, theImage->Data());
592       if (glGetError() != GL_NO_ERROR)
593       {
594         Unbind (theCtx);
595         Release (theCtx.operator->());
596         return false;
597       }
598
599       mySizeX = aWidth;
600       mySizeY = aHeight;
601
602       if (theCtx->arbFBO != NULL)
603       {
604         // generate mipmaps
605         //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
606         theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
607
608         if (glGetError() != GL_NO_ERROR)
609         {
610           Unbind (theCtx);
611           Release (theCtx.operator->());
612           return false;
613         }
614       }
615       else
616       {
617         const TCollection_ExtendedString aWarnMessage ("Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
618
619         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
620
621         Unbind (theCtx);
622         Release (theCtx.operator->());
623         return false;
624       }
625
626       Unbind (theCtx);
627       return true;
628     }
629     default:
630     {
631       Release (theCtx.operator->());
632       return false;
633     }
634   }
635 }
636
637 // =======================================================================
638 // function : Init
639 // purpose  :
640 // =======================================================================
641 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
642                            const Image_PixMap&           theImage,
643                            const Graphic3d_TypeOfTexture theType)
644 {
645   if (theImage.IsEmpty())
646   {
647     Release (theCtx.operator->());
648     return false;
649   }
650
651   GLenum aPixelFormat;
652   GLenum aDataType;
653   GLint aTextFormat;
654   if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType))
655   {
656     Release (theCtx.operator->());
657     return false;
658   }
659
660   return Init (theCtx,
661                aTextFormat, aPixelFormat, aDataType,
662                (Standard_Integer)theImage.SizeX(),
663                (Standard_Integer)theImage.SizeY(),
664                theType, &theImage);
665 }
666
667 // =======================================================================
668 // function : Init2DMultisample
669 // purpose  :
670 // =======================================================================
671 bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx,
672                                         const GLsizei                 theNbSamples,
673                                         const GLint                   theTextFormat,
674                                         const GLsizei                 theSizeX,
675                                         const GLsizei                 theSizeY)
676 {
677   if (!Create (theCtx)
678     || theNbSamples > theCtx->MaxMsaaSamples()
679     || theNbSamples < 1)
680   {
681     return false;
682   }
683
684   const GLsizei aNbSamples = OpenGl_Context::GetPowerOfTwo (theNbSamples, theCtx->MaxMsaaSamples());
685   myTarget = GL_TEXTURE_2D_MULTISAMPLE;
686   if(theSizeX > theCtx->MaxTextureSize()
687   || theSizeY > theCtx->MaxTextureSize())
688   {
689     return false;
690   }
691
692   Bind (theCtx);
693   //myTextFormat = theTextFormat;
694 #if !defined(GL_ES_VERSION_2_0)
695   if (theCtx->Functions()->glTexStorage2DMultisample != NULL)
696   {
697     theCtx->Functions()->glTexStorage2DMultisample (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
698   }
699   else
700   {
701     theCtx->Functions()->glTexImage2DMultisample   (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
702   }
703 #else
704   theCtx->Functions()  ->glTexStorage2DMultisample (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
705 #endif
706   if (theCtx->core11fwd->glGetError() != GL_NO_ERROR)
707   {
708     Unbind (theCtx);
709     return false;
710   }
711
712   mySizeX = theSizeX;
713   mySizeY = theSizeY;
714
715   Unbind (theCtx);
716   return true;
717 }
718
719 // =======================================================================
720 // function : InitRectangle
721 // purpose  :
722 // =======================================================================
723 bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
724                                     const Standard_Integer        theSizeX,
725                                     const Standard_Integer        theSizeY,
726                                     const OpenGl_TextureFormat&   theFormat)
727 {
728   if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (3, 0))
729   {
730     return false;
731   }
732
733 #if !defined(GL_ES_VERSION_2_0)
734   myTarget = GL_TEXTURE_RECTANGLE;
735
736   const GLsizei aSizeX    = Min (theCtx->MaxTextureSize(), theSizeX);
737   const GLsizei aSizeY    = Min (theCtx->MaxTextureSize(), theSizeY);
738   const GLenum  aFilter   = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
739   const GLenum  aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
740
741   Bind (theCtx);
742   glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, aFilter);
743   glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, aFilter);
744   glTexParameteri (myTarget, GL_TEXTURE_WRAP_S,     aWrapMode);
745   glTexParameteri (myTarget, GL_TEXTURE_WRAP_T,     aWrapMode);
746
747   const GLint anIntFormat = theFormat.Internal();
748   myTextFormat = theFormat.Format();
749
750   glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE,
751                 0,
752                 anIntFormat,
753                 aSizeX,
754                 aSizeY,
755                 0,
756                 theFormat.Format(),
757                 GL_FLOAT,
758                 NULL);
759
760   GLint aTestSizeX = 0;
761   GLint aTestSizeY = 0;
762
763   glGetTexLevelParameteriv (
764     GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH,  &aTestSizeX);
765   glGetTexLevelParameteriv (
766     GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
767
768   if (aTestSizeX == 0 || aTestSizeY == 0)
769   {
770     Unbind (theCtx);
771     return false;
772   }
773
774   glTexImage2D (myTarget,
775                 0,
776                 anIntFormat,
777                 aSizeX,
778                 aSizeY,
779                 0,
780                 theFormat.Format(),
781                 GL_FLOAT,
782                 NULL);
783
784   if (glGetError() != GL_NO_ERROR)
785   {
786     Unbind (theCtx);
787     return false;
788   }
789
790   mySizeX = aSizeX;
791   mySizeY = aSizeY;
792
793   Unbind (theCtx);
794   return true;
795 #else
796   (void )theSizeX;
797   (void )theSizeY;
798   (void )theFormat;
799   return false;
800 #endif
801 }
802
803 // =======================================================================
804 // function : Init3D
805 // purpose  :
806 // =======================================================================
807 bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx,
808                              const GLint                   theTextFormat,
809                              const GLenum                  thePixelFormat,
810                              const GLenum                  theDataType,
811                              const Standard_Integer        theSizeX,
812                              const Standard_Integer        theSizeY,
813                              const Standard_Integer        theSizeZ,
814                              const void*                   thePixels)
815 {
816   if (theCtx->Functions()->glTexImage3D == NULL)
817   {
818     TCollection_ExtendedString aMsg ("Error: three-dimensional textures are not supported by hardware.");
819
820     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
821                          GL_DEBUG_TYPE_ERROR,
822                          0,
823                          GL_DEBUG_SEVERITY_HIGH,
824                          aMsg);
825
826     return false;
827   }
828
829   if (!Create(theCtx))
830   {
831     return false;
832   }
833
834   myTarget = GL_TEXTURE_3D;
835
836   const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
837   const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
838   const GLsizei aSizeZ = Min (theCtx->MaxTextureSize(), theSizeZ);
839
840   Bind (theCtx);
841
842   if (theDataType == GL_FLOAT && !theCtx->arbTexFloat)
843   {
844     TCollection_ExtendedString aMsg ("Error: floating-point textures are not supported by hardware.");
845
846     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
847                          GL_DEBUG_TYPE_ERROR,
848                          0,
849                          GL_DEBUG_SEVERITY_HIGH,
850                          aMsg);
851
852     Release (theCtx.operator->());
853     Unbind (theCtx);
854     return false;
855   }
856
857   const GLint anIntFormat = theTextFormat;
858
859 #if !defined (GL_ES_VERSION_2_0)
860   theCtx->core15fwd->glTexImage3D (GL_PROXY_TEXTURE_3D,
861                                    0,
862                                    anIntFormat,
863                                    aSizeX,
864                                    aSizeY,
865                                    aSizeZ,
866                                    0,
867                                    thePixelFormat,
868                                    theDataType,
869                                    NULL);
870
871   GLint aTestSizeX = 0;
872   GLint aTestSizeY = 0;
873   GLint aTestSizeZ = 0;
874
875   glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
876   glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
877   glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &aTestSizeZ);
878
879   if (aTestSizeX == 0 || aTestSizeY == 0 || aTestSizeZ == 0)
880   {
881     Unbind (theCtx);
882     Release (theCtx.operator->());
883     return false;
884   }
885 #endif
886
887   const GLenum aWrapMode = myParams->IsRepeat() ? GL_REPEAT :  theCtx->TextureWrapClamp();
888   const GLenum aFilter   = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
889
890   glTexParameteri (myTarget, GL_TEXTURE_WRAP_S, aWrapMode);
891   glTexParameteri (myTarget, GL_TEXTURE_WRAP_T, aWrapMode);
892   glTexParameteri (myTarget, GL_TEXTURE_WRAP_R, aWrapMode);
893
894   glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, aFilter);
895   glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, aFilter);
896
897   theCtx->Functions()->glTexImage3D (myTarget,
898                                      0,
899                                      anIntFormat,
900                                      aSizeX,
901                                      aSizeY,
902                                      aSizeZ,
903                                      0,
904                                      thePixelFormat,
905                                      theDataType,
906                                      thePixels);
907
908   if (glGetError() != GL_NO_ERROR)
909   {
910     Unbind (theCtx);
911     Release (theCtx.operator->());
912     return false;
913   }
914
915   mySizeX = aSizeX;
916   mySizeY = aSizeY;
917   mySizeZ = aSizeZ;
918
919   Unbind (theCtx);
920   return true;
921 }