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