0025442: Visualization, TKOpenGl - prevent inclusion of system header glxext.h
[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 <Standard_Assert.hxx>
22 #include <Image_PixMap.hxx>
23
24 IMPLEMENT_STANDARD_HANDLE (OpenGl_Texture, OpenGl_Resource)
25 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_Resource)
26
27 //! Simple class to reset unpack alignment settings
28 struct OpenGl_UnpackAlignmentSentry
29 {
30
31   //! Reset unpack alignment settings to safe values
32   void Reset()
33   {
34     glPixelStorei (GL_UNPACK_ALIGNMENT,  1);
35   #if !defined(GL_ES_VERSION_2_0)
36     glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
37   #endif
38   }
39
40   ~OpenGl_UnpackAlignmentSentry()
41   {
42     Reset();
43   }
44
45 };
46
47 // =======================================================================
48 // function : OpenGl_Texture
49 // purpose  :
50 // =======================================================================
51 OpenGl_Texture::OpenGl_Texture (const Handle(Graphic3d_TextureParams)& theParams)
52 : OpenGl_Resource(),
53   myTextureId (NO_TEXTURE),
54   myTarget (GL_TEXTURE_2D),
55   mySizeX (0),
56   mySizeY (0),
57   myTextFormat (GL_RGBA),
58   myHasMipmaps (Standard_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->IsGlGreaterEqual (1, 5))
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->IsGlGreaterEqual (1, 5))
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       theTextFormat = GL_ALPHA8; // GL_R8, GL_R32F
185       thePixelFormat = GL_ALPHA; // GL_RED
186       theDataType    = GL_FLOAT;
187       return true;
188     }
189     case Image_PixMap::ImgRGBAF:
190     {
191       theTextFormat = GL_RGBA8; // GL_RGBA32F
192       thePixelFormat = GL_RGBA;
193       theDataType    = GL_FLOAT;
194       return true;
195     }
196     case Image_PixMap::ImgBGRAF:
197     {
198       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
199       {
200         return false;
201       }
202       theTextFormat  = GL_RGBA8;    // GL_RGBA32F
203       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
204       theDataType    = GL_FLOAT;
205       return true;
206     }
207     case Image_PixMap::ImgRGBF:
208     {
209       theTextFormat = GL_RGB8; // GL_RGB32F
210       thePixelFormat = GL_RGB;
211       theDataType    = GL_FLOAT;
212       return true;
213     }
214     case Image_PixMap::ImgBGRF:
215     {
216     #if !defined(GL_ES_VERSION_2_0)
217       theTextFormat  = GL_RGB8; // GL_RGB32F
218       thePixelFormat = GL_BGR;  // equals to GL_BGR_EXT
219       theDataType    = GL_FLOAT;
220       return true;
221     #else
222       return false;
223     #endif
224     }
225     case Image_PixMap::ImgRGBA:
226     {
227       theTextFormat = GL_RGBA8;
228       thePixelFormat = GL_RGBA;
229       theDataType    = GL_UNSIGNED_BYTE;
230       return true;
231     }
232     case Image_PixMap::ImgBGRA:
233     {
234       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
235       {
236         return false;
237       }
238       theTextFormat  = GL_RGBA8;
239       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
240       theDataType    = GL_UNSIGNED_BYTE;
241       return true;
242     }
243     case Image_PixMap::ImgRGB32:
244     {
245       theTextFormat = GL_RGB8;
246       thePixelFormat = GL_RGBA;
247       theDataType    = GL_UNSIGNED_BYTE;
248       return true;
249     }
250     case Image_PixMap::ImgBGR32:
251     {
252       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
253       {
254         return false;
255       }
256       theTextFormat  = GL_RGB8;
257       thePixelFormat = GL_BGRA_EXT; // equals to GL_BGRA
258       theDataType    = GL_UNSIGNED_BYTE;
259       return true;
260     }
261     case Image_PixMap::ImgRGB:
262     {
263       theTextFormat = GL_RGB8;
264       thePixelFormat = GL_RGB;
265       theDataType    = GL_UNSIGNED_BYTE;
266       return true;
267     }
268     case Image_PixMap::ImgBGR:
269     {
270     #if !defined(GL_ES_VERSION_2_0)
271       if (!theCtx->IsGlGreaterEqual (1, 2) && !theCtx->extBgra)
272       {
273         return false;
274       }
275       theTextFormat = GL_RGB8;
276       thePixelFormat = GL_BGR; // equals to GL_BGR_EXT
277       theDataType    = GL_UNSIGNED_BYTE;
278       return true;
279     #else
280       return false;
281     #endif
282     }
283     case Image_PixMap::ImgGray:
284     {
285       theTextFormat = GL_ALPHA8; // GL_R8
286       thePixelFormat = GL_ALPHA; // GL_RED
287       theDataType    = GL_UNSIGNED_BYTE;
288       return true;
289     }
290     default:
291     {
292       return false;
293     }
294   }
295 }
296
297 // =======================================================================
298 // function : Init
299 // purpose  :
300 // =======================================================================
301 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
302                            const Standard_Integer        theTextFormat,
303                            const GLenum                  thePixelFormat,
304                            const GLenum                  theDataType,
305                            const Standard_Integer        theSizeX,
306                            const Standard_Integer        theSizeY,
307                            const Graphic3d_TypeOfTexture theType,
308                            const Image_PixMap*           theImage)
309 {
310   if (!Create (theCtx))
311   {
312     Release (theCtx.operator->());
313     return false;
314   }
315   myHasMipmaps             = Standard_False;
316   myTextFormat             = thePixelFormat;
317 #if !defined(GL_ES_VERSION_2_0)
318   const GLint anIntFormat  = theTextFormat;
319 #else
320   // ES does not support sized formats and format conversions - them detected from data type
321   const GLint anIntFormat  = thePixelFormat;
322 #endif
323   const GLsizei aWidth     = theSizeX;
324   const GLsizei aHeight    = theSizeY;
325   const GLsizei aMaxSize   = theCtx->MaxTextureSize();
326
327   // Notice that formally general NPOT textures are required by OpenGL 2.0 specifications
328   // however some hardware (NV30 - GeForce FX, RadeOn 9xxx and Xxxx) supports GLSL but not NPOT!
329   // Trying to create NPOT textures on such hardware will not fail
330   // but driver will fall back into software rendering,
331   const bool    toForceP2  = !theCtx->IsGlGreaterEqual (3, 0) && !theCtx->arbNPTW;
332   const GLsizei aWidthOut  = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aWidth,  aMaxSize) : Min (aWidth,  aMaxSize);
333   const GLsizei aHeightOut = toForceP2 ? OpenGl_Context::GetPowerOfTwo (aHeight, aMaxSize) : Min (aHeight, aMaxSize);
334
335 #if !defined(GL_ES_VERSION_2_0)
336   GLint aTestWidth  = 0;
337   GLint aTestHeight = 0;
338 #endif
339   GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
340
341   // setup the alignment
342   OpenGl_UnpackAlignmentSentry anUnpackSentry;
343   if (aDataPtr != NULL)
344   {
345     const GLint anAligment = Min ((GLint )theImage->MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
346     glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
347
348   #if !defined(GL_ES_VERSION_2_0)
349     // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
350     const GLint anExtraBytes = GLint(theImage->RowExtraBytes());
351     const GLint aPixelsWidth = GLint(theImage->SizeRowBytes() / theImage->SizePixelBytes());
352     glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
353   #endif
354   }
355
356   switch (theType)
357   {
358     case Graphic3d_TOT_1D:
359     {
360     #if !defined(GL_ES_VERSION_2_0)
361       myTarget = GL_TEXTURE_1D;
362       Bind (theCtx);
363       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
364       glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
365
366       Image_PixMap aCopy;
367       if (aDataPtr != NULL)
368       {
369         if (aWidth != aWidthOut)
370         {
371           glPixelStorei (GL_PACK_ALIGNMENT,  1);
372           glPixelStorei (GL_PACK_ROW_LENGTH, 0);
373           if (!aCopy.InitTrash (theImage->Format(), Standard_Size(aWidthOut), 1)
374             || gluScaleImage (thePixelFormat,
375                               aWidth,    1, theDataType, theImage->Data(),
376                               aWidthOut, 1, theDataType, aCopy.ChangeData()) != 0)
377           {
378             Unbind (theCtx);
379             Release (theCtx.operator->());
380             return false;
381           }
382
383           aDataPtr = (GLvoid* )aCopy.Data();
384           anUnpackSentry.Reset();
385         }
386       }
387
388       // use proxy to check texture could be created or not
389       glTexImage1D (GL_PROXY_TEXTURE_1D, 0, anIntFormat,
390                     aWidthOut, 0,
391                     thePixelFormat, theDataType, NULL);
392       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
393       if (aTestWidth == 0)
394       {
395         // no memory or broken input parameters
396         Unbind (theCtx);
397         Release (theCtx.operator->());
398         return false;
399       }
400
401       glTexImage1D (GL_TEXTURE_1D, 0, anIntFormat,
402                     aWidthOut, 0,
403                     thePixelFormat, theDataType, aDataPtr);
404       if (glGetError() != GL_NO_ERROR)
405       {
406         Unbind (theCtx);
407         Release (theCtx.operator->());
408         return false;
409       }
410
411       mySizeX = aWidthOut;
412       mySizeY = 1;
413
414       Unbind (theCtx);
415       return true;
416     #else
417       return false;
418     #endif
419     }
420     case Graphic3d_TOT_2D:
421     {
422       myTarget = GL_TEXTURE_2D;
423       Bind (theCtx);
424       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
425       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
426
427       Image_PixMap aCopy;
428       if (aDataPtr != NULL)
429       {
430         if (aWidth != aWidthOut || aHeight != aHeightOut)
431         {
432         #if !defined(GL_ES_VERSION_2_0)
433           // scale texture
434           glPixelStorei (GL_PACK_ALIGNMENT,  1);
435           glPixelStorei (GL_PACK_ROW_LENGTH, 0);
436           if (!aCopy.InitTrash (theImage->Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut))
437             || gluScaleImage (thePixelFormat,
438                               aWidth,    aHeight,    theDataType, theImage->Data(),
439                               aWidthOut, aHeightOut, theDataType, aCopy.ChangeData()) != 0)
440           {
441             Unbind (theCtx);
442             Release (theCtx.operator->());
443             return false;
444           }
445
446           aDataPtr = (GLvoid* )aCopy.Data();
447           anUnpackSentry.Reset();
448         #else
449           Unbind (theCtx);
450           Release (theCtx.operator->());
451           return false;
452         #endif
453         }
454       }
455
456     #if !defined(GL_ES_VERSION_2_0)
457       // use proxy to check texture could be created or not
458       glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
459                     aWidthOut, aHeightOut, 0,
460                     thePixelFormat, theDataType, NULL);
461       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &aTestWidth);
462       glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
463       if (aTestWidth == 0 || aTestHeight == 0)
464       {
465         // no memory or broken input parameters
466         Unbind (theCtx);
467         Release (theCtx.operator->());
468         return false;
469       }
470     #endif
471
472       glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
473                     aWidthOut, aHeightOut, 0,
474                     thePixelFormat, theDataType, aDataPtr);
475       if (glGetError() != GL_NO_ERROR)
476       {
477         Unbind (theCtx);
478         Release (theCtx.operator->());
479         return false;
480       }
481
482       mySizeX = aWidthOut;
483       mySizeY = aHeightOut;
484
485       Unbind (theCtx);
486       return true;
487     }
488     case Graphic3d_TOT_2D_MIPMAP:
489     {
490       myTarget     = GL_TEXTURE_2D;
491       myHasMipmaps = Standard_True;
492       Bind (theCtx);
493       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
494       glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
495
496       if (theCtx->arbFBO != NULL
497        && aWidth == aWidthOut && aHeight == aHeightOut)
498       {
499       #if !defined(GL_ES_VERSION_2_0)
500         // use proxy to check texture could be created or not
501         glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
502                       aWidthOut, aHeightOut, 0,
503                       thePixelFormat, theDataType, NULL);
504         glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &aTestWidth);
505         glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
506         if (aTestWidth == 0 || aTestHeight == 0)
507         {
508           // no memory or broken input parameters
509           Unbind (theCtx);
510           Release (theCtx.operator->());
511           return false;
512         }
513       #endif
514
515         // upload main picture
516         glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
517                       aWidthOut, aHeightOut, 0,
518                       thePixelFormat, theDataType, theImage->Data());
519         if (glGetError() != GL_NO_ERROR)
520         {
521           Unbind (theCtx);
522           Release (theCtx.operator->());
523           return false;
524         }
525
526         mySizeX = aWidthOut;
527         mySizeY = aHeightOut;
528
529         // generate mipmaps
530         //glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
531         theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
532
533         Unbind (theCtx);
534         return true;
535       }
536       else
537       {
538       #if !defined(GL_ES_VERSION_2_0)
539         bool isCreated = gluBuild2DMipmaps (GL_TEXTURE_2D, anIntFormat,
540                                             aWidth, aHeight,
541                                             thePixelFormat, theDataType, theImage->Data()) == 0;
542         if (isCreated)
543         {
544           glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &mySizeX);
545           glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &mySizeY);
546         }
547
548         Unbind (theCtx);
549         return isCreated;
550       #else
551         Unbind (theCtx);
552         return false;
553       #endif
554       }
555     }
556     default:
557     {
558       Release (theCtx.operator->());
559       return false;
560     }
561   }
562 }
563
564 // =======================================================================
565 // function : Init
566 // purpose  :
567 // =======================================================================
568 bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
569                            const Image_PixMap&           theImage,
570                            const Graphic3d_TypeOfTexture theType)
571 {
572   if (theImage.IsEmpty())
573   {
574     Release (theCtx.operator->());
575     return false;
576   }
577
578   GLenum aPixelFormat;
579   GLenum aDataType;
580   GLint aTextFormat;
581   if (!GetDataFormat (theCtx, theImage, aTextFormat, aPixelFormat, aDataType))
582   {
583     Release (theCtx.operator->());
584     return false;
585   }
586
587   return Init (theCtx,
588                aTextFormat, aPixelFormat, aDataType,
589                (Standard_Integer)theImage.SizeX(),
590                (Standard_Integer)theImage.SizeY(),
591                theType, &theImage);
592 }
593
594 // =======================================================================
595 // function : InitRectangle
596 // purpose  :
597 // =======================================================================
598 bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
599                                     const Standard_Integer        theSizeX,
600                                     const Standard_Integer        theSizeY,
601                                     const OpenGl_TextureFormat&   theFormat)
602 {
603   if (!Create (theCtx) || !theCtx->IsGlGreaterEqual (3, 0))
604   {
605     return false;
606   }
607
608 #if !defined(GL_ES_VERSION_2_0)
609   myTarget = GL_TEXTURE_RECTANGLE;
610
611   const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
612   const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
613
614   Bind (theCtx);
615
616   if (myParams->Filter() == Graphic3d_TOTF_NEAREST)
617   {
618     glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
619     glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
620   }
621   else
622   {
623     glTexParameteri (myTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
624     glTexParameteri (myTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
625   }
626
627   const GLint anIntFormat = theFormat.Internal();
628   myTextFormat = theFormat.Format();
629
630   glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE,
631                 0,
632                 anIntFormat,
633                 aSizeX,
634                 aSizeY,
635                 0,
636                 theFormat.Format(),
637                 GL_FLOAT,
638                 NULL);
639
640   GLint aTestSizeX = 0;
641   GLint aTestSizeY = 0;
642
643   glGetTexLevelParameteriv (
644     GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH,  &aTestSizeX);
645   glGetTexLevelParameteriv (
646     GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
647
648   if (aTestSizeX == 0 || aTestSizeY == 0)
649   {
650     Unbind (theCtx);
651     return false;
652   }
653
654   glTexImage2D (myTarget,
655                 0,
656                 anIntFormat,
657                 aSizeX,
658                 aSizeY,
659                 0,
660                 theFormat.Format(),
661                 GL_FLOAT,
662                 NULL);
663
664   if (glGetError() != GL_NO_ERROR)
665   {
666     Unbind (theCtx);
667     return false;
668   }
669
670   mySizeX = aSizeX;
671   mySizeY = aSizeY;
672
673   Unbind (theCtx);
674   return true;
675 #else
676   return false;
677 #endif
678 }