0025132: Visualization - treat any TopoDS_Solid as closed volume
[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
24IMPLEMENT_STANDARD_HANDLE (OpenGl_Texture, OpenGl_Resource)
25IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_Resource)
26
74706083 27//! Simple class to reset unpack alignment settings
28struct OpenGl_UnpackAlignmentSentry
29{
30
31 //! Reset unpack alignment settings to safe values
32 void Reset()
33 {
34 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
35 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
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),
55 myTextFormat (GL_FLOAT),
56 myHasMipmaps (Standard_False),
57 myParams (theParams)
58{
59 if (myParams.IsNull())
60 {
61 myParams = new Graphic3d_TextureParams();
62 }
63}
64
65// =======================================================================
66// function : ~OpenGl_Texture
67// purpose :
68// =======================================================================
69OpenGl_Texture::~OpenGl_Texture()
70{
71 Release (NULL);
72}
73
74// =======================================================================
75// function : HasMipmaps
76// purpose :
77// =======================================================================
78const Standard_Boolean OpenGl_Texture::HasMipmaps() const
79{
80 return myHasMipmaps;
81}
82
83// =======================================================================
84// function : GetParams
85// purpose :
86// =======================================================================
87const Handle(Graphic3d_TextureParams)& OpenGl_Texture::GetParams() const
88{
89 return myParams;
90}
91
92// =======================================================================
93// function : SetParams
94// purpose :
95// =======================================================================
96void OpenGl_Texture::SetParams (const Handle(Graphic3d_TextureParams)& theParams)
97{
98 myParams = theParams;
99}
100
101// =======================================================================
102// function : Create
103// purpose :
104// =======================================================================
105bool OpenGl_Texture::Create (const Handle(OpenGl_Context)& )
106{
107 if (myTextureId == NO_TEXTURE)
108 {
109 glGenTextures (1, &myTextureId);
110 }
111 return myTextureId != NO_TEXTURE;
112}
113
114// =======================================================================
115// function : Release
116// purpose :
117// =======================================================================
118void OpenGl_Texture::Release (const OpenGl_Context* theGlCtx)
119{
120 if (myTextureId == NO_TEXTURE)
121 {
122 return;
123 }
124
125 // application can not handle this case by exception - this is bug in code
126 Standard_ASSERT_RETURN (theGlCtx != NULL,
127 "OpenGl_Texture destroyed without GL context! Possible GPU memory leakage...",);
128
ec2eeb2d 129 if (theGlCtx->IsValid())
130 {
131 glDeleteTextures (1, &myTextureId);
132 }
bf75be98 133 myTextureId = NO_TEXTURE;
134 mySizeX = mySizeY = 0;
135}
136
137// =======================================================================
138// function : Bind
139// purpose :
140// =======================================================================
141void OpenGl_Texture::Bind (const Handle(OpenGl_Context)& theCtx,
142 const GLenum theTextureUnit) const
143{
01ca42b2 144 if (theCtx->IsGlGreaterEqual (1, 5))
bf75be98 145 {
01ca42b2 146 theCtx->core15fwd->glActiveTexture (theTextureUnit);
bf75be98 147 }
148 glBindTexture (myTarget, myTextureId);
149}
150
151// =======================================================================
152// function : Unbind
153// purpose :
154// =======================================================================
155void OpenGl_Texture::Unbind (const Handle(OpenGl_Context)& theCtx,
156 const GLenum theTextureUnit) const
157{
01ca42b2 158 if (theCtx->IsGlGreaterEqual (1, 5))
bf75be98 159 {
01ca42b2 160 theCtx->core15fwd->glActiveTexture (theTextureUnit);
bf75be98 161 }
162 glBindTexture (myTarget, NO_TEXTURE);
163}
164
18f4e8e2 165//=======================================================================
166//function : GetDataFormat
167//purpose :
168//=======================================================================
169bool OpenGl_Texture::GetDataFormat (const Handle(OpenGl_Context)& theCtx,
170 const Image_PixMap& theData,
171 GLint& theTextFormat,
172 GLenum& thePixelFormat,
173 GLenum& theDataType)
bf75be98 174{
18f4e8e2 175 theTextFormat = GL_RGBA8;
176 thePixelFormat = 0;
177 theDataType = 0;
178 switch (theData.Format())
bf75be98 179 {
180 case Image_PixMap::ImgGrayF:
181 {
18f4e8e2 182 theTextFormat = GL_ALPHA8; // GL_R8, GL_R32F
183 thePixelFormat = GL_ALPHA; // GL_RED
184 theDataType = GL_FLOAT;
185 return true;
bf75be98 186 }
187 case Image_PixMap::ImgRGBAF:
188 {
18f4e8e2 189 theTextFormat = GL_RGBA8; // GL_RGBA32F
190 thePixelFormat = GL_RGBA;
191 theDataType = GL_FLOAT;
192 return true;
bf75be98 193 }
194 case Image_PixMap::ImgBGRAF:
195 {
196 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
197 {
198 return false;
199 }
18f4e8e2 200 theTextFormat = GL_RGBA8; // GL_RGBA32F
201 thePixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
202 theDataType = GL_FLOAT;
203 return true;
bf75be98 204 }
205 case Image_PixMap::ImgRGBF:
206 {
18f4e8e2 207 theTextFormat = GL_RGB8; // GL_RGB32F
208 thePixelFormat = GL_RGB;
209 theDataType = GL_FLOAT;
210 return true;
bf75be98 211 }
212 case Image_PixMap::ImgBGRF:
213 {
18f4e8e2 214 theTextFormat = GL_RGB8; // GL_RGB32F
215 thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
216 theDataType = GL_FLOAT;
217 return true;
bf75be98 218 }
219 case Image_PixMap::ImgRGBA:
220 {
18f4e8e2 221 theTextFormat = GL_RGBA8;
222 thePixelFormat = GL_RGBA;
223 theDataType = GL_UNSIGNED_BYTE;
224 return true;
bf75be98 225 }
226 case Image_PixMap::ImgBGRA:
227 {
228 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
229 {
230 return false;
231 }
18f4e8e2 232 theTextFormat = GL_RGBA8;
233 thePixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
234 theDataType = GL_UNSIGNED_BYTE;
235 return true;
bf75be98 236 }
237 case Image_PixMap::ImgRGB32:
238 {
18f4e8e2 239 theTextFormat = GL_RGB8;
240 thePixelFormat = GL_RGBA;
241 theDataType = GL_UNSIGNED_BYTE;
242 return true;
bf75be98 243 }
244 case Image_PixMap::ImgBGR32:
245 {
246 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
247 {
248 return false;
249 }
18f4e8e2 250 theTextFormat = GL_RGB8;
251 thePixelFormat = GL_BGRA; // equals to GL_BGRA_EXT
252 theDataType = GL_UNSIGNED_BYTE;
253 return true;
bf75be98 254 }
255 case Image_PixMap::ImgRGB:
256 {
18f4e8e2 257 theTextFormat = GL_RGB8;
258 thePixelFormat = GL_RGB;
259 theDataType = GL_UNSIGNED_BYTE;
260 return true;
bf75be98 261 }
262 case Image_PixMap::ImgBGR:
263 {
264 if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
265 {
266 return false;
267 }
18f4e8e2 268 theTextFormat = GL_RGB8;
269 thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
270 theDataType = GL_UNSIGNED_BYTE;
271 return true;
bf75be98 272 }
273 case Image_PixMap::ImgGray:
274 {
18f4e8e2 275 theTextFormat = GL_ALPHA8; // GL_R8
276 thePixelFormat = GL_ALPHA; // GL_RED
277 theDataType = GL_UNSIGNED_BYTE;
278 return true;
bf75be98 279 }
280 default:
281 {
282 return false;
283 }
284 }
18f4e8e2 285}
bf75be98 286
18f4e8e2 287// =======================================================================
288// function : Init
289// purpose :
290// =======================================================================
291bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
292 const Standard_Integer theTextFormat,
293 const GLenum thePixelFormat,
294 const GLenum theDataType,
295 const Standard_Integer theSizeX,
296 const Standard_Integer theSizeY,
297 const Graphic3d_TypeOfTexture theType,
298 const Image_PixMap* theImage)
299{
300 if (!Create (theCtx))
301 {
302 Release (theCtx.operator->());
303 return false;
304 }
305 myHasMipmaps = Standard_False;
306 myTextFormat = theTextFormat;
307 const GLsizei aWidth = theSizeX;
308 const GLsizei aHeight = theSizeY;
bf75be98 309 const GLsizei aMaxSize = theCtx->MaxTextureSize();
bf75be98 310
311 // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
312 // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
68333c8f 313 // Trying to create NPOT textures on such hardware will not fail
bf75be98 314 // but driver will fall back into software rendering,
315 const bool toForceP2 = !theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW;
a174a3c5 316 const GLsizei aWidthOut = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aWidth, aMaxSize) : Min (aWidth, aMaxSize);
317 const GLsizei aHeightOut = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize) : Min (aHeight, aMaxSize);
bf75be98 318
319 GLint aTestWidth = 0;
320 GLint aTestHeight = 0;
18f4e8e2 321 GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
bf75be98 322
74706083 323 // setup the alignment
324 OpenGl_UnpackAlignmentSentry anUnpackSentry;
18f4e8e2 325 if (aDataPtr != NULL)
326 {
327 const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
328 glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
74706083 329
18f4e8e2 330 // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
331 const GLint anExtraBytes = GLint(theImage->RowExtraBytes());
332 const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes());
333 glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
334 }
74706083 335
bf75be98 336 switch (theType)
337 {
338 case Graphic3d_TOT_1D:
339 {
340 myTarget = GL_TEXTURE_1D;
341 Bind (theCtx);
342 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
343 glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
344
345 Image_PixMap aCopy;
18f4e8e2 346 if (aDataPtr != NULL)
bf75be98 347 {
18f4e8e2 348 if (aWidth != aWidthOut)
bf75be98 349 {
18f4e8e2 350 glPixelStorei (GL_PACK_ALIGNMENT, 1);
351 glPixelStorei (GL_PACK_ROW_LENGTH, 0);
352 if (!aCopy.InitTrash (theImage->Format(), Standard_Size(aWidthOut), 1)
353 || gluScaleImage (thePixelFormat,
354 aWidth, 1, theDataType, theImage->Data(),
355 aWidthOut, 1, theDataType, aCopy.ChangeData()) != 0)
356 {
357 Unbind (theCtx);
358 Release (theCtx.operator->());
359 return false;
360 }
361
362 aDataPtr = (GLvoid* )aCopy.Data();
363 anUnpackSentry.Reset();
bf75be98 364 }
bf75be98 365 }
366
367 // use proxy to check texture could be created or not
a577aaab 368 glTexImage1D (GL_PROXY_TEXTURE_1D, 0, myTextFormat,
bf75be98 369 aWidthOut, 0,
18f4e8e2 370 thePixelFormat, theDataType, NULL);
bf75be98 371 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
372 if (aTestWidth == 0)
373 {
374 // no memory or broken input parameters
375 Unbind (theCtx);
18f4e8e2 376 Release (theCtx.operator->());
bf75be98 377 return false;
378 }
379
a577aaab 380 glTexImage1D (GL_TEXTURE_1D, 0, myTextFormat,
bf75be98 381 aWidthOut, 0,
18f4e8e2 382 thePixelFormat, theDataType, aDataPtr);
a174a3c5 383 if (glGetError() != GL_NO_ERROR)
384 {
385 Unbind (theCtx);
18f4e8e2 386 Release (theCtx.operator->());
a174a3c5 387 return false;
388 }
389
390 mySizeX = aWidthOut;
391 mySizeY = 1;
bf75be98 392
393 Unbind (theCtx);
394 return true;
395 }
396 case Graphic3d_TOT_2D:
397 {
398 myTarget = GL_TEXTURE_2D;
399 Bind (theCtx);
400 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
401 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
402
403 Image_PixMap aCopy;
18f4e8e2 404 if (aDataPtr != NULL)
bf75be98 405 {
18f4e8e2 406 if (aWidth != aWidthOut || aHeight != aHeightOut)
bf75be98 407 {
18f4e8e2 408 // scale texture
409 glPixelStorei (GL_PACK_ALIGNMENT, 1);
410 glPixelStorei (GL_PACK_ROW_LENGTH, 0);
411 if (!aCopy.InitTrash (theImage->Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut))
412 || gluScaleImage (thePixelFormat,
413 aWidth, aHeight, theDataType, theImage->Data(),
414 aWidthOut, aHeightOut, theDataType, aCopy.ChangeData()) != 0)
415 {
416 Unbind (theCtx);
417 Release (theCtx.operator->());
418 return false;
419 }
420
421 aDataPtr = (GLvoid* )aCopy.Data();
422 anUnpackSentry.Reset();
bf75be98 423 }
bf75be98 424 }
425
426 // use proxy to check texture could be created or not
a577aaab 427 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, myTextFormat,
bf75be98 428 aWidthOut, aHeightOut, 0,
18f4e8e2 429 thePixelFormat, theDataType, NULL);
bf75be98 430 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
431 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
432 if (aTestWidth == 0 || aTestHeight == 0)
433 {
434 // no memory or broken input parameters
435 Unbind (theCtx);
18f4e8e2 436 Release (theCtx.operator->());
bf75be98 437 return false;
438 }
439
a577aaab 440 glTexImage2D (GL_TEXTURE_2D, 0, myTextFormat,
bf75be98 441 aWidthOut, aHeightOut, 0,
18f4e8e2 442 thePixelFormat, theDataType, aDataPtr);
a174a3c5 443 if (glGetError() != GL_NO_ERROR)
444 {
445 Unbind (theCtx);
18f4e8e2 446 Release (theCtx.operator->());
a174a3c5 447 return false;
448 }
449
450 mySizeX = aWidthOut;
451 mySizeY = aHeightOut;
bf75be98 452
453 Unbind (theCtx);
454 return true;
455 }
456 case Graphic3d_TOT_2D_MIPMAP:
457 {
458 myTarget = GL_TEXTURE_2D;
459 myHasMipmaps = Standard_True;
460 Bind (theCtx);
461 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
462 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
463
01ca42b2 464 if (theCtx->arbFBO != NULL
1a7dfdb7 465 && aWidth == aWidthOut && aHeight == aHeightOut)
466 {
467 // use proxy to check texture could be created or not
a577aaab 468 glTexImage2D (GL_PROXY_TEXTURE_2D, 0, myTextFormat,
1a7dfdb7 469 aWidthOut, aHeightOut, 0,
18f4e8e2 470 thePixelFormat, theDataType, NULL);
1a7dfdb7 471 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
472 glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
473 if (aTestWidth == 0 || aTestHeight == 0)
474 {
475 // no memory or broken input parameters
476 Unbind (theCtx);
18f4e8e2 477 Release (theCtx.operator->());
1a7dfdb7 478 return false;
479 }
480
481 // upload main picture
a577aaab 482 glTexImage2D (GL_TEXTURE_2D, 0, myTextFormat,
1a7dfdb7 483 aWidthOut, aHeightOut, 0,
18f4e8e2 484 thePixelFormat, theDataType, theImage->Data());
a174a3c5 485 if (glGetError() != GL_NO_ERROR)
486 {
487 Unbind (theCtx);
18f4e8e2 488 Release (theCtx.operator->());
a174a3c5 489 return false;
490 }
491
492 mySizeX = aWidthOut;
493 mySizeY = aHeightOut;
1a7dfdb7 494
495 // generate mipmaps
496 //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
01ca42b2 497 theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
1a7dfdb7 498
499 Unbind (theCtx);
500 return true;
501 }
502 else
503 {
a577aaab 504 bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, myTextFormat,
1a7dfdb7 505 aWidth, aHeight,
18f4e8e2 506 thePixelFormat, theDataType, theImage->Data()) == 0;
a174a3c5 507 if (isCreated)
508 {
509 glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &mySizeX);
510 glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &mySizeY);
511 }
512
1a7dfdb7 513 Unbind (theCtx);
514 return isCreated;
515 }
bf75be98 516 }
517 default:
518 {
18f4e8e2 519 Release (theCtx.operator->());
bf75be98 520 return false;
521 }
522 }
523}
68333c8f 524
525// =======================================================================
18f4e8e2 526// function : Init
527// purpose :
528// =======================================================================
529bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
530 const Image_PixMap& theImage,
531 const Graphic3d_TypeOfTexture theType)
532{
533 if (theImage.IsEmpty())
534 {
535 Release (theCtx.operator->());
536 return false;
537 }
538
539 GLenum aPixelFormat;
540 GLenum aDataType;
541 GLint aTextFormat;
542 if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType))
543 {
544 Release (theCtx.operator->());
545 return false;
546 }
547
548 return Init (theCtx,
549 aTextFormat, aPixelFormat, aDataType,
550 (Standard_Integer)theImage.SizeX(),
551 (Standard_Integer)theImage.SizeY(),
552 theType, &theImage);
553}
554
555// =======================================================================
68333c8f 556// function : InitRectangle
557// purpose :
558// =======================================================================
559bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
560 const Standard_Integer theSizeX,
561 const Standard_Integer theSizeY,
562 const OpenGl_TextureFormat& theFormat)
563{
564 if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (3, 0))
565 {
566 return false;
567 }
568
569 myTarget = GL_TEXTURE_RECTANGLE;
570
571 const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
572 const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
573
574 Bind (theCtx);
575
576 if (myParams->Filter() == Graphic3d_TOTF_NEAREST)
577 {
578 glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
579 glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
580 }
581 else
582 {
583 glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
584 glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
585 }
586
587 myTextFormat = theFormat.Internal();
588
589 glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE,
590 0,
591 myTextFormat,
592 aSizeX,
593 aSizeY,
594 0,
595 theFormat.Format(),
596 GL_FLOAT,
597 NULL);
598
599 GLint aTestSizeX = 0;
600 GLint aTestSizeY = 0;
601
602 glGetTexLevelParameteriv (
603 GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
604 glGetTexLevelParameteriv (
605 GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
606
607 if (aTestSizeX == 0 || aTestSizeY == 0)
608 {
609 Unbind (theCtx);
610 return false;
611 }
612
613 glTexImage2D (myTarget,
614 0,
615 myTextFormat,
616 aSizeX,
617 aSizeY,
618 0,
619 theFormat.Format(),
620 GL_FLOAT,
621 NULL);
622
623 if (glGetError() != GL_NO_ERROR)
624 {
625 Unbind (theCtx);
626 return false;
627 }
628
629 mySizeX = aSizeX;
630 mySizeY = aSizeY;
631
632 Unbind (theCtx);
633 return true;
634}