0025162: Visualization, TKOpenGl - drop GLU library dependency
[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_GlCore15.hxx>
20 #include <Graphic3d_TextureParams.hxx>
21 #include <TCollection_ExtendedString.hxx>
22 #include <Standard_Assert.hxx>
23 #include <Image_PixMap.hxx>
24
25
26 //! Simple class to reset unpack alignment settings
27 struct OpenGl_UnpackAlignmentSentry
28 {
29
30   //! Reset unpack alignment settings to safe values
31   void Reset()
32   {
33     glPixelStorei (GL_UNPACK_ALIGNMENT,  1);
34   #if !defined(GL_ES_VERSION_2_0)
35     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
36   #endif
37   }
38
39   ~OpenGl_UnpackAlignmentSentry()
40   {
41     Reset();
42   }
43
44 };
45
46 // =======================================================================
47 // function : OpenGl_Texture
48 // purpose  :
49 // =======================================================================
50 OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
51 : OpenGl_Resource(),
52   myTextureId (NO_TEXTURE),
53   myTarget (GL_TEXTURE_2D),
54   mySizeX (0),
55   mySizeY (0),
56   myTextFormat (GL_RGBA),
57   myHasMipmaps (Standard_False),
58   myIsAlpha    (false),
59   myParams     (theParams)
60 {
61   if (myParams.IsNull())
62   {
63     myParams = new Graphic3d_TextureParams();
64   }
65 }
66
67 // =======================================================================
68 // function : ~OpenGl_Texture
69 // purpose  :
70 // =======================================================================
71 OpenGl_Texture::~OpenGl_Texture()
72 {
73   Release (NULL);
74 }
75
76 // =======================================================================
77 // function : HasMipmaps
78 // purpose  :
79 // =======================================================================
80 const Standard_Boolean OpenGl_Texture::HasMipmaps() const
81 {
82   return myHasMipmaps;
83 }
84
85 // =======================================================================
86 // function : GetParams
87 // purpose  :
88 // =======================================================================
89 const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
90 {
91   return myParams;
92 }
93
94 // =======================================================================
95 // function : SetParams
96 // purpose  :
97 // =======================================================================
98 void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
99 {
100   myParams = theParams;
101 }
102
103 // =======================================================================
104 // function : Create
105 // purpose  :
106 // =======================================================================
107 bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
108 {
109   if (myTextureId == NO_TEXTURE)
110   {
111     glGenTextures (1, &myTextureId);
112   }
113   return myTextureId != NO_TEXTURE;
114 }
115
116 // =======================================================================
117 // function : Release
118 // purpose  :
119 // =======================================================================
120 void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
121 {
122   if (myTextureId == NO_TEXTURE)
123   {
124     return;
125   }
126
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...",);
130
131   if (theGlCtx->IsValid())
132   {
133     glDeleteTextures (1, &myTextureId);
134   }
135   myTextureId = NO_TEXTURE;
136   mySizeX = mySizeY = 0;
137 }
138
139 // =======================================================================
140 // function : Bind
141 // purpose  :
142 // =======================================================================
143 void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
144                            const GLenum theTextureUnit) const
145 {
146   if (theCtx->core15fwd != NULL)
147   {
148     theCtx->core15fwd->glActiveTexture (theTextureUnit);
149   }
150   glBindTexture (myTarget, myTextureId);
151 }
152
153 // =======================================================================
154 // function : Unbind
155 // purpose  :
156 // =======================================================================
157 void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
158                              const GLenum theTextureUnit) const
159 {
160   if (theCtx->core15fwd != NULL)
161   {
162     theCtx->core15fwd->glActiveTexture (theTextureUnit);
163   }
164   glBindTexture (myTarget, NO_TEXTURE);
165 }
166
167 //=======================================================================
168 //function : GetDataFormat
169 //purpose  :
170 //=======================================================================
171 bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
172                                     const Image_PixMap&           theData,
173                                     GLint&                        theTextFormat,
174                                     GLenum&                       thePixelFormat,
175                                     GLenum&                       theDataType)
176 {
177   theTextFormat  = GL_RGBA8;
178   thePixelFormat = 0;
179   theDataType    = 0;
180   switch (theData.Format())
181   {
182     case Image_PixMap::ImgGrayF:
183     {
184       if (theCtx->core11 == NULL)
185       {
186         theTextFormat  = GL_R8;  // GL_R32F
187         thePixelFormat = GL_RED;
188       }
189       else
190       {
191         theTextFormat  = GL_LUMINANCE8;
192         thePixelFormat = GL_LUMINANCE;
193       }
194       theDataType = GL_FLOAT;
195       return true;
196     }
197     case Image_PixMap::ImgAlphaF:
198     {
199       if (theCtx->core11 == NULL)
200       {
201         theTextFormat  = GL_R8;  // GL_R32F
202         thePixelFormat = GL_RED;
203       }
204       else
205       {
206         theTextFormat  = GL_ALPHA8;
207         thePixelFormat = GL_ALPHA;
208       }
209       theDataType = GL_FLOAT;
210       return true;
211     }
212     case Image_PixMap::ImgRGBAF:
213     {
214       theTextFormat  = GL_RGBA8; // GL_RGBA32F
215       thePixelFormat = GL_RGBA;
216       theDataType    = GL_FLOAT;
217       return true;
218     }
219     case Image_PixMap::ImgBGRAF:
220     {
221       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
222       {
223         return false;
224       }
225       theTextFormat  = GL_RGBA8;    // GL_RGBA32F
226       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
227       theDataType    = GL_FLOAT;
228       return true;
229     }
230     case Image_PixMap::ImgRGBF:
231     {
232       theTextFormat  = GL_RGB8; // GL_RGB32F
233       thePixelFormat = GL_RGB;
234       theDataType    = GL_FLOAT;
235       return true;
236     }
237     case Image_PixMap::ImgBGRF:
238     {
239     #if !defined(GL_ES_VERSION_2_0)
240       theTextFormat  = GL_RGB8; // GL_RGB32F
241       thePixelFormat = GL_BGR;  // equals to GL_BGR_EXT
242       theDataType    = GL_FLOAT;
243       return true;
244     #else
245       return false;
246     #endif
247     }
248     case Image_PixMap::ImgRGBA:
249     {
250       theTextFormat = GL_RGBA8;
251       thePixelFormat = GL_RGBA;
252       theDataType    = GL_UNSIGNED_BYTE;
253       return true;
254     }
255     case Image_PixMap::ImgBGRA:
256     {
257       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
258       {
259         return false;
260       }
261       theTextFormat  = GL_RGBA8;
262       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
263       theDataType    = GL_UNSIGNED_BYTE;
264       return true;
265     }
266     case Image_PixMap::ImgRGB32:
267     {
268       theTextFormat = GL_RGB8;
269       thePixelFormat = GL_RGBA;
270       theDataType    = GL_UNSIGNED_BYTE;
271       return true;
272     }
273     case Image_PixMap::ImgBGR32:
274     {
275       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
276       {
277         return false;
278       }
279       theTextFormat  = GL_RGB8;
280       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
281       theDataType    = GL_UNSIGNED_BYTE;
282       return true;
283     }
284     case Image_PixMap::ImgRGB:
285     {
286       theTextFormat = GL_RGB8;
287       thePixelFormat = GL_RGB;
288       theDataType    = GL_UNSIGNED_BYTE;
289       return true;
290     }
291     case Image_PixMap::ImgBGR:
292     {
293     #if !defined(GL_ES_VERSION_2_0)
294       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
295       {
296         return false;
297       }
298       theTextFormat = GL_RGB8;
299       thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
300       theDataType    = GL_UNSIGNED_BYTE;
301       return true;
302     #else
303       return false;
304     #endif
305     }
306     case Image_PixMap::ImgGray:
307     {
308       if (theCtx->core11 == NULL)
309       {
310         theTextFormat  = GL_R8;
311         thePixelFormat = GL_RED;
312       }
313       else
314       {
315         theTextFormat  = GL_LUMINANCE8;
316         thePixelFormat = GL_LUMINANCE;
317       }
318       theDataType = GL_UNSIGNED_BYTE;
319       return true;
320     }
321     case Image_PixMap::ImgAlpha:
322     {
323       if (theCtx->core11 == NULL)
324       {
325         theTextFormat  = GL_R8;
326         thePixelFormat = GL_RED;
327       }
328       else
329       {
330         theTextFormat  = GL_ALPHA8;
331         thePixelFormat = GL_ALPHA;
332       }
333       theDataType = GL_UNSIGNED_BYTE;
334       return true;
335     }
336     case Image_PixMap::ImgUNKNOWN:
337     {
338       return false;
339     }
340   }
341   return false;
342 }
343
344 // =======================================================================
345 // function : Init
346 // purpose  :
347 // =======================================================================
348 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
349                            const Standard_Integer        theTextFormat,
350                            const GLenum                  thePixelFormat,
351                            const GLenum                  theDataType,
352                            const Standard_Integer        theSizeX,
353                            const Standard_Integer        theSizeY,
354                            const Graphic3d_TypeOfTexture theType,
355                            const Image_PixMap*           theImage)
356 {
357   if (!Create (theCtx))
358   {
359     Release (theCtx.operator->());
360     return false;
361   }
362
363   if (theImage != NULL)
364   {
365     myIsAlpha = theImage->Format() == Image_PixMap::ImgAlpha
366              || theImage->Format() == Image_PixMap::ImgAlphaF;
367   }
368   else
369   {
370     myIsAlpha = thePixelFormat == GL_ALPHA;
371   }
372
373   myHasMipmaps             = Standard_False;
374   myTextFormat             = thePixelFormat;
375 #if !defined(GL_ES_VERSION_2_0)
376   const GLint anIntFormat  = theTextFormat;
377 #else
378   // ES does not support sized formats and format conversions - them detected from data type
379   const GLint anIntFormat  = thePixelFormat;
380 #endif
381   const GLsizei aWidth     = theSizeX;
382   const GLsizei aHeight    = theSizeY;
383   const GLsizei aMaxSize   = theCtx->MaxTextureSize();
384
385   if (aWidth > aMaxSize || aHeight > aMaxSize)
386   {
387     TCollection_ExtendedString aWarnMessage = TCollection_ExtendedString ("Error: Texture dimension - ")
388       + aWidth + "x" + aHeight + " exceeds hardware limits (" + aMaxSize + "x" + aMaxSize + ")";
389
390     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
391     Release (theCtx.operator->());
392     return false;
393   }
394 #if !defined(GL_ES_VERSION_2_0)
395   else if (!theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW)
396   {
397     // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
398     // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
399     // Trying to create NPOT textures on such hardware will not fail
400     // but driver will fall back into software rendering,
401     const GLsizei aWidthP2  = OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize);
402     const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize);
403
404     if (aWidth != aWidthP2 || (theType != Graphic3d_TOT_1D && aHeight != aHeightP2))
405     {
406       TCollection_ExtendedString aWarnMessage =
407         TCollection_ExtendedString ("Error: NPOT Textures (") + aWidth + "x" + aHeight + ") are not supported by hardware.";
408
409       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
410
411       Release (theCtx.operator->());
412       return false;
413     }
414   }
415 #else
416   else if (!theCtx->IsGlGreaterEqual (3, 0) && theType == Graphic3d_TOT_2D_MIPMAP)
417   {
418     // Mipmap NPOT textures are not supported by OpenGL ES 2.0.
419     const GLsizei aWidthP2  = OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize);
420     const GLsizei aHeightP2 = OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize);
421
422     if (aWidth != aWidthP2 || aHeight != aHeightP2)
423     {
424       TCollection_ExtendedString aWarnMessage =
425         TCollection_ExtendedString ("Error: Mipmap NPOT Textures (") + aWidth + "x" + aHeight + ") are not supported by OpenGL ES 2.0";
426
427       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
428
429       Release (theCtx.operator->());
430       return false;
431     }
432   }
433 #endif
434
435   const GLenum  aFilter   = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
436   const GLenum  aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
437
438 #if !defined(GL_ES_VERSION_2_0)
439   GLint aTestWidth  = 0;
440   GLint aTestHeight = 0;
441 #endif
442   GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
443
444   // setup the alignment
445   OpenGl_UnpackAlignmentSentry anUnpackSentry;
446   (void)anUnpackSentry; // avoid compiler warning
447
448   if (aDataPtr != NULL)
449   {
450     const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
451     glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
452
453   #if !defined(GL_ES_VERSION_2_0)
454     // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
455     const GLint anExtraBytes = GLint(theImage->RowExtraBytes());
456     const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes());
457     glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
458   #endif
459   }
460
461   switch (theType)
462   {
463     case Graphic3d_TOT_1D:
464     {
465     #if !defined(GL_ES_VERSION_2_0)
466       myTarget = GL_TEXTURE_1D;
467       Bind (theCtx);
468       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
469       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
470       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
471
472       // use proxy to check texture could be created or not
473       glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
474                     aWidth, 0,
475                     thePixelFormat, theDataType, NULL);
476       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
477       if (aTestWidth == 0)
478       {
479         // no memory or broken input parameters
480         Unbind (theCtx);
481         Release (theCtx.operator->());
482         return false;
483       }
484
485       glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
486                     aWidth, 0,
487                     thePixelFormat, theDataType, aDataPtr);
488       if (glGetError() != GL_NO_ERROR)
489       {
490         Unbind (theCtx);
491         Release (theCtx.operator->());
492         return false;
493       }
494
495       mySizeX = aWidth;
496       mySizeY = 1;
497
498       Unbind (theCtx);
499       return true;
500     #else
501       Release (theCtx.operator->());
502       return false;
503     #endif
504     }
505     case Graphic3d_TOT_2D:
506     {
507       myTarget = GL_TEXTURE_2D;
508       Bind (theCtx);
509       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilter);
510       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
511       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
512       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
513
514     #if !defined(GL_ES_VERSION_2_0)
515       // use proxy to check texture could be created or not
516       glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
517                     aWidth, aHeight, 0,
518                     thePixelFormat, theDataType, NULL);
519       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &aTestWidth);
520       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
521       if (aTestWidth == 0 || aTestHeight == 0)
522       {
523         // no memory or broken input parameters
524         Unbind (theCtx);
525         Release (theCtx.operator->());
526         return false;
527       }
528     #endif
529
530       glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
531                     aWidth, aHeight, 0,
532                     thePixelFormat, theDataType, aDataPtr);
533       if (glGetError() != GL_NO_ERROR)
534       {
535         Unbind (theCtx);
536         Release (theCtx.operator->());
537         return false;
538       }
539
540       mySizeX = aWidth;
541       mySizeY = aHeight;
542
543       Unbind (theCtx);
544       return true;
545     }
546     case Graphic3d_TOT_2D_MIPMAP:
547     {
548       myTarget     = GL_TEXTURE_2D;
549       myHasMipmaps = Standard_True;
550
551       GLenum aFilterMin = aFilter;
552       aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
553       if (myParams->Filter() == Graphic3d_TOTF_BILINEAR)
554       {
555         aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
556       }
557       else if (myParams->Filter() == Graphic3d_TOTF_TRILINEAR)
558       {
559         aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
560       }
561
562       Bind (theCtx);
563       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
564       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
565       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
566       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
567
568     #if !defined(GL_ES_VERSION_2_0)
569       // use proxy to check texture could be created or not
570       glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
571                     aWidth, aHeight, 0,
572                     thePixelFormat, theDataType, NULL);
573       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &aTestWidth);
574       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
575       if (aTestWidth == 0 || aTestHeight == 0)
576       {
577         // no memory or broken input parameters
578         Unbind (theCtx);
579         Release (theCtx.operator->());
580         return false;
581       }
582     #endif
583
584       // upload main picture
585       glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
586                     aWidth, aHeight, 0,
587                     thePixelFormat, theDataType, theImage->Data());
588       if (glGetError() != GL_NO_ERROR)
589       {
590         Unbind (theCtx);
591         Release (theCtx.operator->());
592         return false;
593       }
594
595       mySizeX = aWidth;
596       mySizeY = aHeight;
597
598       if (theCtx->arbFBO != NULL)
599       {
600         // generate mipmaps
601         //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
602         theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
603
604         if (glGetError() != GL_NO_ERROR)
605         {
606           Unbind (theCtx);
607           Release (theCtx.operator->());
608           return false;
609         }
610       }
611       else
612       {
613         const TCollection_ExtendedString aWarnMessage ("Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
614
615         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aWarnMessage);
616
617         Unbind (theCtx);
618         Release (theCtx.operator->());
619         return false;
620       }
621
622       Unbind (theCtx);
623       return true;
624     }
625     default:
626     {
627       Release (theCtx.operator->());
628       return false;
629     }
630   }
631 }
632
633 // =======================================================================
634 // function : Init
635 // purpose  :
636 // =======================================================================
637 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
638                            const Image_PixMap&           theImage,
639                            const Graphic3d_TypeOfTexture theType)
640 {
641   if (theImage.IsEmpty())
642   {
643     Release (theCtx.operator->());
644     return false;
645   }
646
647   GLenum aPixelFormat;
648   GLenum aDataType;
649   GLint aTextFormat;
650   if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType))
651   {
652     Release (theCtx.operator->());
653     return false;
654   }
655
656   return Init (theCtx,
657                aTextFormat, aPixelFormat, aDataType,
658                (Standard_Integer)theImage.SizeX(),
659                (Standard_Integer)theImage.SizeY(),
660                theType, &theImage);
661 }
662
663 // =======================================================================
664 // function : InitRectangle
665 // purpose  :
666 // =======================================================================
667 bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
668                                     const Standard_Integer        theSizeX,
669                                     const Standard_Integer        theSizeY,
670                                     const OpenGl_TextureFormat&   theFormat)
671 {
672   if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (3, 0))
673   {
674     return false;
675   }
676
677 #if !defined(GL_ES_VERSION_2_0)
678   myTarget = GL_TEXTURE_RECTANGLE;
679
680   const GLsizei aSizeX    = Min (theCtx->MaxTextureSize(), theSizeX);
681   const GLsizei aSizeY    = Min (theCtx->MaxTextureSize(), theSizeY);
682   const GLenum  aFilter   = (myParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
683   const GLenum  aWrapMode = myParams->IsRepeat() ? GL_REPEAT : theCtx->TextureWrapClamp();
684
685   Bind (theCtx);
686   glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, aFilter);
687   glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, aFilter);
688   glTexParameteri (myTarget, GL_TEXTURE_WRAP_S,     aWrapMode);
689   glTexParameteri (myTarget, GL_TEXTURE_WRAP_T,     aWrapMode);
690
691   const GLint anIntFormat = theFormat.Internal();
692   myTextFormat = theFormat.Format();
693
694   glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE,
695                 0,
696                 anIntFormat,
697                 aSizeX,
698                 aSizeY,
699                 0,
700                 theFormat.Format(),
701                 GL_FLOAT,
702                 NULL);
703
704   GLint aTestSizeX = 0;
705   GLint aTestSizeY = 0;
706
707   glGetTexLevelParameteriv (
708     GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH,  &aTestSizeX);
709   glGetTexLevelParameteriv (
710     GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
711
712   if (aTestSizeX == 0 || aTestSizeY == 0)
713   {
714     Unbind (theCtx);
715     return false;
716   }
717
718   glTexImage2D (myTarget,
719                 0,
720                 anIntFormat,
721                 aSizeX,
722                 aSizeY,
723                 0,
724                 theFormat.Format(),
725                 GL_FLOAT,
726                 NULL);
727
728   if (glGetError() != GL_NO_ERROR)
729   {
730     Unbind (theCtx);
731     return false;
732   }
733
734   mySizeX = aSizeX;
735   mySizeY = aSizeY;
736
737   Unbind (theCtx);
738   return true;
739 #else
740   return false;
741 #endif
742 }