Back to index

nux  3.0.0
IOpenGLSurface.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "GLResource.h"
00024 #include "GraphicsDisplay.h"
00025 #include "GpuDevice.h"
00026 #include "GLDeviceObjects.h"
00027 #include "IOpenGLSurface.h"
00028 
00029 namespace nux
00030 {
00031 
00032   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLSurface);
00033 
00034   IOpenGLSurface::IOpenGLSurface(IOpenGLBaseTexture *DeviceBaseTexture
00035     , GLenum OpenGLID
00036     , GLenum TextureTarget
00037     , GLenum SurfaceTarget
00038     , int MipLevel
00039     , int Slice
00040     , NUX_FILE_LINE_DECL)
00041     : IOpenGLResource(RTSURFACE, NUX_FILE_LINE_PARAM)
00042     , _STextureTarget(TextureTarget)
00043     , _SSurfaceTarget(SurfaceTarget)
00044     , _SMipLevel(MipLevel)
00045     , _SSlice(Slice)
00046     , _BaseTexture(DeviceBaseTexture)
00047     , _AllocatedUnpackBuffer(0xFFFFFFFF)
00048   {
00049     // IOpenGLSurface surfaces are created inside a IOpenGLTexture2D, IOpenGLCubeTexture and IOpenGLVolumeTexture.
00050     // They reside within those classes. The reference counting starts once a call to GetSurfaceLevel,
00051     // GetCubeMapSurface or GetVolumeLevel is made to the container object.
00052     _RefCount = 0;
00053     _OpenGLID = OpenGLID;
00054     _LockedRect.pBits = 0;
00055     _LockedRect.Pitch = 0;
00056     _CompressedDataSize = 0;
00057     _Initialized = 0;
00058   }
00059 
00060   IOpenGLSurface::~IOpenGLSurface()
00061   {
00062 
00063   }
00064 
00065   BitmapFormat IOpenGLSurface::GetPixelFormat() const
00066   {
00067     if (_BaseTexture == 0)
00068     {
00069       nuxAssert(0);  // should not happen
00070       return BITFMT_UNKNOWN;
00071     }
00072 
00073     return _BaseTexture->GetPixelFormat();
00074   }
00075 
00076   int IOpenGLSurface::GetWidth() const
00077   {
00078     if (_BaseTexture == 0)
00079     {
00080       nuxAssert(0);  // should not happen
00081       return 0;
00082     }
00083 
00084     return ImageSurface::GetLevelDim(_BaseTexture->_PixelFormat, _BaseTexture->_Width, _SMipLevel);
00085   }
00086 
00087   int IOpenGLSurface::GetHeight() const
00088   {
00089     if (_BaseTexture == 0)
00090     {
00091       nuxAssert(0);  // should not happen
00092       return 0;
00093     }
00094 
00095     return ImageSurface::GetLevelDim(_BaseTexture->_PixelFormat, _BaseTexture->_Height, _SMipLevel);
00096   }
00097 
00098   int IOpenGLSurface::GetMipLevel() const
00099   {
00100     return _SMipLevel;
00101   }
00102 
00103   int IOpenGLSurface::GetSurfaceTarget() const
00104   {
00105     return _SSurfaceTarget;
00106   }
00107 
00108   int IOpenGLSurface::GetDesc(SURFACE_DESC *pDesc)
00109   {
00110     pDesc->Width    = GetWidth();
00111     pDesc->Height   = GetHeight();
00112     pDesc->PixelFormat   = GetPixelFormat();
00113     pDesc->Type     = _ResourceType;
00114     return OGL_OK;
00115   }
00116 
00117   int IOpenGLSurface::RefCount() const
00118   {
00119     if (_BaseTexture)
00120       return _BaseTexture->RefCount();
00121 
00122     nuxAssert(0); // Surface with no underlying texture. That should not happen.
00123     return 0;
00124   }
00125 
00126   int IOpenGLSurface::LockRect(
00127     SURFACE_LOCKED_RECT *pLockedRect,
00128     const SURFACE_RECT *pRect)
00129   {
00130     // If _LockedRect.pBits or _LockedRect.Pitch are not equal to zero, then we have already Locked the buffer
00131     // Unlock it before locking again.
00132     nuxAssert(_LockedRect.pBits == 0);
00133     nuxAssert(_LockedRect.Pitch == 0);
00134     nuxAssert(_CompressedDataSize == 0);
00135 
00136     if ((_LockedRect.pBits != 0) || (_LockedRect.Pitch != 0) || (_CompressedDataSize != 0))
00137     {
00138       // already locked;
00139       return OGL_INVALID_LOCK;
00140     }
00141 
00142     _Rect.bottom = _Rect.left = _Rect.right = _Rect.top = 0;
00143 
00144     GLint unpack_alignment = GPixelFormats[_BaseTexture->_PixelFormat].RowMemoryAlignment;
00145     unsigned int halfUnpack = Log2(unpack_alignment);
00146 
00147     CHECKGL(glBindTexture(_STextureTarget, _BaseTexture->_OpenGLID));
00148 
00149     unsigned int surface_size = 0;
00150     unsigned int BytePerPixel = 0;
00151 
00152     IOpenGLBaseTexture *texture = _BaseTexture;
00153 
00154     if (!((_BaseTexture->_ResourceType == RTTEXTURE) ||
00155           (_BaseTexture->_ResourceType == RTTEXTURERECTANGLE) ||
00156           (_BaseTexture->_ResourceType == RTCUBETEXTURE) ||
00157           (_BaseTexture->_ResourceType == RTVOLUMETEXTURE) ||
00158           (_BaseTexture->_ResourceType == RTANIMATEDTEXTURE)))
00159     {
00160       nuxAssertMsg(0, "Unknown resource type");
00161     }
00162 
00163     int texwidth, texheight;
00164     texwidth = ImageSurface::GetLevelDim(texture->_PixelFormat, texture->_Width, _SMipLevel);
00165     texheight = ImageSurface::GetLevelDim(texture->_PixelFormat, texture->_Height, _SMipLevel);
00166 
00167     if ( texture->_PixelFormat == BITFMT_DXT1 ||
00168          texture->_PixelFormat == BITFMT_DXT2 ||
00169          texture->_PixelFormat == BITFMT_DXT3 ||
00170          texture->_PixelFormat == BITFMT_DXT4 ||
00171          texture->_PixelFormat == BITFMT_DXT5)
00172     {
00173       if (texture->_PixelFormat == BITFMT_DXT1)
00174       {
00175         // We can conceive a 4x4 DXT1 block as if each texel uses 4 bits.
00176         // Actually, for DXT, we have 2 16-bits colors(5:6:5), and each texel uses 2 bits to interpolate
00177         // between the 2 colors.
00178         //    ---------------------
00179         //    |      COLOR0       | 16 bits
00180         //    ---------------------
00181         //    |      COLOR1       | 16 bits
00182         //    ---------------------
00183         //    | xx | xx | xx | xx | xx = 2 bits
00184         //    ---------------------
00185         //    | xx | xx | xx | xx |
00186         //    ---------------------
00187         //    | xx | xx | xx | xx |
00188         //    ---------------------
00189         //    | xx | xx | xx | xx |
00190         //    ---------------------
00191 
00192         // A line of n texel DXT1 data uses n/2 bytes(4 bits/texel). So the number of bytes used for a
00193         // texwidth texel, is texwidth/2 bytes.
00194         // Note that texwidth is divisible by 4(to to the upper rounding to 4), therefore, it is also divisible
00195         // by 2.
00196 
00197         // glCompressedTexImage2DARB, glCompressedTexImage3DARB,
00198         // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei.
00199         surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel);
00200         _CompressedDataSize = surface_size;
00201         _LockedRect.Pitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel);
00202 
00203         if (_Initialized == false)
00204         {
00205           InitializeLevel();
00206         }
00207       }
00208       else
00209       {
00210         // A line of n texel DXT3/5 data uses n bytes(1 byte/texel). So the number of bytes used for a
00211         // texwidth texels, is texwidth bytes.
00212 
00213         // glCompressedTexImage2DARB, glCompressedTexImage3DARB,
00214         // glCompressedTexSubImage2DARB, glCompressedTexSubImage3DARB are not affected by glPixelStorei.
00215         surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel);
00216         _CompressedDataSize = surface_size;
00217         _LockedRect.Pitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel);
00218 
00219         if (_Initialized == false)
00220         {
00221           InitializeLevel();
00222         }
00223       }
00224     }
00225     else
00226     {
00227       _LockedRect.Pitch = ImageSurface::GetLevelPitch(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel);
00228       surface_size = ImageSurface::GetLevelSize(texture->_PixelFormat, texture->_Width, texture->_Height, _SMipLevel);
00229 
00230       if (_Initialized == false)
00231       {
00232         InitializeLevel();
00233       }
00234     }
00235 
00236     _Rect.left  = 0;
00237     _Rect.top   = 0;
00238     _Rect.bottom  = texheight;
00239     _Rect.right   = texwidth;
00240 
00241 
00242     if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects())
00243     {
00244       GetGraphicsDisplay()->GetGpuDevice()->AllocateUnpackPixelBufferIndex(&_AllocatedUnpackBuffer);
00245     }
00246 
00247     if (pRect == 0)
00248     {
00249       if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects())
00250       {
00251         // Mapping the entire area of the surface
00252         _LockedRect.pBits = GetGraphicsDisplay()->GetGpuDevice()->LockUnpackPixelBufferIndex(_AllocatedUnpackBuffer, surface_size);
00253         pLockedRect->pBits = _LockedRect.pBits;
00254         pLockedRect->Pitch = _LockedRect.Pitch;
00255       }
00256       else
00257       {
00258         //[DEBUGGING - NO PBO]
00259         // Mapping the entire area of the surface
00260         _LockedRect.pBits = new BYTE[surface_size];
00261         pLockedRect->pBits = _LockedRect.pBits;
00262         pLockedRect->Pitch = _LockedRect.Pitch;
00263       }
00264     }
00265     else
00266     {
00267       //[WARNING]
00268       // this section of code is suppose to handle rectangles that are not the size of the entire surface.
00269       // It works for uncompressed texture. However it hasn't been tested for compressed texture.
00270 
00271       // reserve and lock a surface size equal  to(RectWidth * RectHeight * BytePerPixel)
00272       int RectWidth = pRect->right - pRect->left;
00273       int RectHeight = pRect->bottom - pRect->top;
00274 
00275       nuxAssert(RectWidth >= 0);
00276       nuxAssert(RectHeight >= 0);
00277 
00278 
00279       unsigned int RectSize = (((RectWidth * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack)) * RectHeight;
00280 
00281       if (RectSize == 0)
00282       {
00283         _LockedRect.pBits = NULL;
00284         _LockedRect.Pitch = 0;
00285         pLockedRect->pBits = NULL;
00286         pLockedRect->Pitch = 0;
00287         return OGL_INVALID_LOCK;
00288       }
00289 
00290       if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects())
00291       {
00292         _LockedRect.pBits = GetGraphicsDisplay()->GetGpuDevice()->LockUnpackPixelBufferIndex(_AllocatedUnpackBuffer, RectSize);
00293         pLockedRect->pBits = ((BYTE *) _LockedRect.pBits);
00294         pLockedRect->Pitch = (((RectWidth * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack));
00295       }
00296       else
00297       {
00298         //[DEBUGGING - NO PBO]
00299         _LockedRect.pBits = new BYTE[RectSize];
00300         pLockedRect->pBits = ((BYTE *) _LockedRect.pBits);
00301         pLockedRect->Pitch = (((RectWidth * BytePerPixel + (unpack_alignment - 1)) >> (halfUnpack)) << (halfUnpack));
00302       }
00303 
00304       _Rect.left  = pRect->left;
00305       _Rect.top   = pRect->top;
00306       _Rect.bottom  = pRect->bottom;
00307       _Rect.right   = pRect->right;
00308     }
00309 
00310     return OGL_OK;
00311   }
00312 
00313   int IOpenGLSurface::UnlockRect()
00314   {
00315     if (_LockedRect.pBits == 0)
00316     {
00317       return OGL_INVALID_UNLOCK;
00318     }
00319 
00320     CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, _BaseTexture->GetFormatRowMemoryAlignment()));
00321 
00322     BYTE *DataPtr = 0;
00323 
00324 #ifndef NUX_OPENGLES_20
00325     if (_STextureTarget == GL_TEXTURE_2D || _STextureTarget == GL_TEXTURE_RECTANGLE_ARB || _STextureTarget == GL_TEXTURE_CUBE_MAP || _STextureTarget == GL_TEXTURE_3D)
00326 #else
00327     if (_STextureTarget == GL_TEXTURE_2D)
00328 #endif
00329     {
00330       int w = _Rect.right - _Rect.left;
00331       int h = _Rect.bottom - _Rect.top;
00332       CHECKGL(glBindTexture(_STextureTarget, _BaseTexture->_OpenGLID));
00333 
00334 #ifndef NUX_OPENGLES_20
00335       if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects())
00336       {
00337         // Unmap the texture image buffer
00338         GetGraphicsDisplay()->GetGpuDevice()->BindUnpackPixelBufferIndex(_AllocatedUnpackBuffer);
00339         CHECKGL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB));
00340         DataPtr = NUX_BUFFER_OFFSET(0);
00341       }
00342       else
00343       {
00344         CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
00345 #endif
00346         DataPtr = (BYTE *) _LockedRect.pBits;
00347 #ifndef NUX_OPENGLES_20
00348       }
00349 #endif
00350 
00351       IOpenGLTexture2D *texture = (IOpenGLTexture2D *) _BaseTexture;
00352 
00353 #ifndef NUX_OPENGLES_20
00354       if ( /*texture->_PixelFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||*/
00355         texture->_PixelFormat == BITFMT_DXT1 ||
00356         texture->_PixelFormat == BITFMT_DXT2 ||
00357         texture->_PixelFormat == BITFMT_DXT3 ||
00358         texture->_PixelFormat == BITFMT_DXT4 ||
00359         texture->_PixelFormat == BITFMT_DXT5)
00360       {
00361         nuxAssert(_CompressedDataSize != 0);
00362         int width = Max<int> (1, texture->_Width >> _SMipLevel);
00363         int height = Max<int> (1, texture->_Height >> _SMipLevel);
00364 
00365         int xoffset = _Rect.left;
00366         int yoffset = _Rect.top;
00367 
00368         if (_STextureTarget != GL_TEXTURE_3D)
00369         {
00370           glCompressedTexSubImage2DARB(_SSurfaceTarget,
00371                                         _SMipLevel,                 // level
00372                                         xoffset,
00373                                         yoffset,
00374                                         width,
00375                                         height,
00376                                         GPixelFormats[texture->_PixelFormat].PlatformFormat,
00377                                         _CompressedDataSize,        // image Size
00378                                         DataPtr                     // data
00379                                        );
00380           CHECKGL_MSG(glCompressedTexSubImage2DARB);
00381         }
00382         else
00383         {
00384           glCompressedTexSubImage3DARB(_SSurfaceTarget,
00385                                         _SMipLevel,                 // level
00386                                         xoffset,
00387                                         yoffset,
00388                                         0,
00389                                         width,
00390                                         height,
00391                                         _SSlice,
00392                                         GPixelFormats[texture->_PixelFormat].PlatformFormat,
00393                                         _CompressedDataSize,        // image Size
00394                                         DataPtr                     // data
00395                                        );
00396           CHECKGL_MSG(glCompressedTexSubImage3DARB);
00397         }
00398 
00399         // We can use glCompressedTexImage2DARB if we are sure we always lock
00400         // the entire area of the surface.
00401         //            glCompressedTexImage2DARB(_SSurfaceTarget,
00402         //                _SMipLevel,                 // level
00403         //                texture->_Format,
00404         //                width,
00405         //                height,
00406         //                0,                          // border
00407         //                _CompressedDataSize,        // image Size
00408         //                _LockedRect.pBits           // data
00409         //                );
00410         //            CHECKGL_MSG(glCompressedTexImage2DARB);
00411 
00412 
00413         //            { //[DEBUGGING - Red Texture]
00414         //                // This is going to put some red in the texture.
00415         //                // The texture is not compressed.
00416         //                BYTE *color_array = new BYTE[width*height*4];
00417         //                for (int i = 0; i < width*height*4; i += 4)
00418         //                {
00419         //                    color_array[i + 0] = 0xff;
00420         //                    color_array[i + 1] = _SMipLevel * 0x3F;
00421         //                    color_array[i + 2] = 0x0;
00422         //                    color_array[i + 3] = 0xFF;
00423         //                }
00424         //                glTexImage2D(GL_TEXTURE_2D,
00425         //                    _SMipLevel,
00426         //                    GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, color_array);
00427         //                CHECKGL_MSG(glTexImage2D);
00428         //                delete [] color_array;
00429         //            }
00430       }
00431       else
00432       {
00433         //CHECKGL(glPixelStorei(GL_UNPACK_ROW_LENGTH, w));
00434         if (_STextureTarget != GL_TEXTURE_3D)
00435         {
00436 #endif
00437           CHECKGL(glTexSubImage2D(_SSurfaceTarget,
00438                                      _SMipLevel,
00439                                      _Rect.left,
00440                                      _Rect.top,
00441                                      w,
00442                                      h,
00443                                      GPixelFormats[texture->_PixelFormat].Format,
00444                                      GPixelFormats[texture->_PixelFormat].type,
00445                                      DataPtr
00446                                     ));
00447 #ifndef NUX_OPENGLES_20
00448         }
00449         else
00450         {
00451           CHECKGL(glTexSubImage3D(_SSurfaceTarget,
00452                                      _SMipLevel,
00453                                      _Rect.left,
00454                                      _Rect.top,
00455                                      _SSlice,          // z offset
00456                                      w,
00457                                      h,
00458                                      1,
00459                                      GPixelFormats[texture->_PixelFormat].Format,
00460                                      GPixelFormats[texture->_PixelFormat].type,
00461                                      DataPtr
00462                                     ));
00463         }
00464 
00465         //CHECKGL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
00466 
00467         //            CHECKGL(glTexImage2D(_SSurfaceTarget,
00468         //                _SMipLevel,
00469         //                GPixelFormats[texture->_PixelFormat].PlatformFormat,
00470         //                w,
00471         //                h,
00472         //                0,
00473         //                //### todo:
00474         //                //  - find the correct format matching the internal format
00475         //                //  - find the correct type matching the internal format
00476         //                GPixelFormats[texture->_PixelFormat].Format,
00477         //                GPixelFormats[texture->_PixelFormat].type,
00478         //                DataPtr
00479         //                ));
00480 
00481       }
00482 #endif
00483     }
00484     else
00485     {
00486       nuxDebugMsg("[IOpenGLSurface::UnlockRect] Incorrect Texture Target.");
00487     }
00488 
00489 #ifndef NUX_OPENGLES_20
00490     if (GetGraphicsDisplay()->GetGpuDevice()->UsePixelBufferObjects())
00491     {
00492       CHECKGL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
00493       GetGraphicsDisplay()->GetGpuDevice()->FreeUnpackPixelBufferIndex(_AllocatedUnpackBuffer);
00494     }
00495     else
00496     {
00497 #endif
00498       //[DEBUGGING - NO PBO]
00499       if (_LockedRect.pBits)
00500       {
00501         delete [] ((BYTE *) _LockedRect.pBits);
00502       }
00503 #ifndef NUX_OPENGLES_20
00504     }
00505 #endif
00506 
00507     CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, GetGraphicsDisplay()->GetGpuDevice()->GetPixelStoreAlignment()));
00508 
00509     _LockedRect.pBits = 0;
00510     _LockedRect.Pitch = 0;
00511     _CompressedDataSize = 0;
00512 
00513     return OGL_OK;
00514   }
00515 
00516   int IOpenGLSurface::InitializeLevel()
00517   {
00518     // Because we use SubImage when unlocking surfaces, we must first get some dummy data in the surface before we can make a lock.
00519     int texwidth = ImageSurface::GetLevelWidth(_BaseTexture->_PixelFormat, _BaseTexture->_Width, _SMipLevel);
00520     int texheight = ImageSurface::GetLevelHeight(_BaseTexture->_PixelFormat, _BaseTexture->_Height, _SMipLevel);
00521     int size = ImageSurface::GetLevelSize(_BaseTexture->_PixelFormat, _BaseTexture->_Width, _BaseTexture->_Height, _SMipLevel);
00522     int MemAlignment = ImageSurface::GetMemAlignment(_BaseTexture->_PixelFormat);
00523 
00524     nuxAssert( texwidth > 0 ); // Should never happen
00525     nuxAssert( texheight > 0 ); // Should never happen
00526     nuxAssert( size > 0 ); // Should never happen
00527 
00528     BYTE *DummyBuffer = (BYTE *) calloc(size, sizeof(BYTE));
00529 
00530     CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, MemAlignment));
00531 
00532 #ifndef NUX_OPENGLES_20
00533     if ( _BaseTexture->_PixelFormat == BITFMT_DXT1 ||
00534          _BaseTexture->_PixelFormat == BITFMT_DXT2 ||
00535          _BaseTexture->_PixelFormat == BITFMT_DXT3 ||
00536          _BaseTexture->_PixelFormat == BITFMT_DXT4 ||
00537          _BaseTexture->_PixelFormat == BITFMT_DXT5)
00538     {
00539       if (_STextureTarget != GL_TEXTURE_3D)
00540       {
00541         glCompressedTexImage2DARB(
00542           _SSurfaceTarget,
00543           _SMipLevel,                 // level
00544           GPixelFormats[_BaseTexture->_PixelFormat].PlatformFormat,
00545           texwidth,
00546           texheight,
00547           0,                          // border
00548           size,                       // image Size
00549           DummyBuffer                           // data
00550         );
00551         CHECKGL_MSG(glCompressedTexImage2DARB);
00552       }
00553       else
00554       {
00555         //             glCompressedTexImage3DARB(
00556         //                 _SSurfaceTarget,
00557         //                 _SMipLevel,                 // level
00558         //                 GPixelFormats[_BaseTexture->_PixelFormat].PlatformFormat,
00559         //                 texwidth,
00560         //                 texheight,
00561         //                 _SSlice,
00562         //                 0,                          // border
00563         //                 size,                       // image Size
00564         //                 DummyBuffer                           // data
00565         //                 );
00566         //             CHECKGL_MSG(glCompressedTexImage3DARB);
00567       }
00568     }
00569     else
00570     {
00571       if (_STextureTarget != GL_TEXTURE_3D)
00572       {
00573 #endif
00574         glTexImage2D(
00575           _SSurfaceTarget,
00576           _SMipLevel,                 // level
00577           GPixelFormats[_BaseTexture->_PixelFormat].PlatformFormat,
00578           texwidth,
00579           texheight,
00580           0,                          // border
00581           GPixelFormats[_BaseTexture->_PixelFormat].Format,
00582           GPixelFormats[_BaseTexture->_PixelFormat].type,
00583           DummyBuffer);
00584         CHECKGL_MSG(glTexImage2D);
00585 #ifndef NUX_OPENGLES_20
00586       }
00587       else
00588       {
00589         //             glTexImage3D(
00590         //                 _SSurfaceTarget,
00591         //                 _SMipLevel,                 // level
00592         //                 GPixelFormats[PixelFormat].PlatformFormat,
00593         //                 texwidth,
00594         //                 texheight,
00595         //                 _SSlice,
00596         //                 0,                          // border
00597         //                 GPixelFormats[PixelFormat].Format,
00598         //                 GPixelFormats[PixelFormat].type,
00599         //                 DummyBuffer);
00600         //             CHECKGL_MSG(glTexImage3D);
00601       }
00602     }
00603 #endif
00604 
00605     free(DummyBuffer);
00606 
00607 
00608     //    { //[DEBUGGING - Red Texture]
00609     //        // This is going to put some red in the texture.
00610     //        // The texture is not compressed.
00611     //        BYTE *color_array = new BYTE[texwidth*texheight*4];
00612     //        for (unsigned int i = 0; i < texwidth*texheight*4; i += 4)
00613     //        {
00614     //            color_array[i + 0] = 0xff;
00615     //            color_array[i + 1] = _SMipLevel * 0x3F;
00616     //            color_array[i + 2] = 0x0;
00617     //            color_array[i + 3] = 0xFF;
00618     //        }
00619     //        glTexImage2D(GL_TEXTURE_2D,
00620     //            _SMipLevel,
00621     //            GL_RGBA8, texwidth, texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, color_array);
00622     //        CHECKGL_MSG(glTexImage2D);
00623     //        delete [] color_array;
00624     //    }
00625 
00626     CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, GetGraphicsDisplay()->GetGpuDevice()->GetPixelStoreAlignment()));
00627 
00628     _Initialized = true;
00629     return OGL_OK;
00630   }
00631 
00632   void IOpenGLSurface::CopyRenderTarget(int x, int y, int width, int height)
00633   {
00634     CHECKGL(glPixelStorei(GL_UNPACK_ALIGNMENT, _BaseTexture->GetFormatRowMemoryAlignment()));
00635 
00636 #ifndef NUX_OPENGLES_20
00637     if (_STextureTarget == GL_TEXTURE_2D || _STextureTarget == GL_TEXTURE_RECTANGLE_ARB || _STextureTarget == GL_TEXTURE_CUBE_MAP || _STextureTarget == GL_TEXTURE_3D)
00638 #else
00639     if (_STextureTarget == GL_TEXTURE_2D)
00640 #endif
00641     {
00642       CHECKGL(glBindTexture(_STextureTarget, _BaseTexture->_OpenGLID));
00643 
00644 
00645 #ifndef NUX_OPENGLES_20
00646       if (_STextureTarget != GL_TEXTURE_3D)
00647       {
00648         CHECKGL(glCopyTexImage2D(_SSurfaceTarget,
00649           _SMipLevel,
00650           GPixelFormats [_BaseTexture->_PixelFormat].Format,
00651           x,
00652           y,
00653           width,
00654           height,
00655           0));
00656       }
00657       else
00658       {
00659         CHECKGL(glCopyTexSubImage3D(_SSurfaceTarget,
00660           _SMipLevel,
00661           0,
00662           0,
00663           0,
00664           x,
00665           y,
00666           width,
00667           height));
00668       }
00669 #else
00670       CHECKGL(glCopyTexImage2D(_SSurfaceTarget,
00671         _SMipLevel,
00672         GPixelFormats [_BaseTexture->_PixelFormat].Format,
00673         x,
00674         y,
00675         width,
00676         height,
00677         0));
00678 #endif
00679     }
00680   }
00681 
00682   unsigned char* IOpenGLSurface::GetSurfaceData(int &width, int &height, int &stride)
00683   {
00684     width = 0;
00685     height = 0;
00686     stride = 0;
00687     
00688     if (_BaseTexture->_OpenGLID == 0)
00689     {
00690       return NULL;
00691     }
00692 
00693 #ifndef NUX_OPENGLES_20
00694     CHECKGL(glBindTexture(_STextureTarget, _BaseTexture->_OpenGLID));
00695 
00696     // Despite a 1 byte pack alignment not being the most optimum, do it for simplicity.
00697     CHECKGL(glPixelStorei(GL_PACK_ALIGNMENT, 1));
00698 
00699     // We want RGBA data
00700     int mip_level_size = GetWidth() * GetHeight() * 4;
00701     unsigned char* img = new unsigned char[mip_level_size];
00702 
00703     // Internal OpenGL textures are in the RGBA format.
00704     // If the selected texture image does not contain four components, the following mappings are applied:
00705     // - Single-component textures are treated as RGBA buffers with red set to the single-component value, green set to 0, blue set to 0, and alpha set to 1.
00706     //   - red set to component zero
00707     //   - green set to 0
00708     //   - blue set to 0
00709     //   - alpha set to 1.0
00710     // - Two-component textures are treated as RGBA buffers with:
00711     //   - red set to component zero
00712     //   - green set to 0
00713     //   - blue set to 0
00714     //   - alpha set to component one
00715     // 
00716     // - Three-component textures are treated as RGBA buffers with:
00717     //   - red set to component zero
00718     //   - green set to component one
00719     //   - blue set to component two
00720     //   - alpha set to 1.0
00721 
00722     CHECKGL(glGetTexImage(_STextureTarget, _SMipLevel, GL_RGBA, GL_UNSIGNED_BYTE, img));
00723 
00724     width = GetWidth();
00725     height = GetHeight(); 
00726     stride = width * 4;
00727 
00728     return img;
00729 #else
00730     //FIXME: need to render to framebuffer and use glReadPixels
00731     return NULL;
00732 #endif
00733   }
00734 }
00735