Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreD3D9Texture.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreD3D9Texture.h"
00026 #include "OgreException.h"
00027 #include "OgreLogManager.h"
00028 #include "OgreStringConverter.h"
00029 #include "OgreBitwise.h"
00030 #include "OgreSDDataChunk.h"
00031 
00032 #include "OgreNoMemoryMacros.h"
00033 #include <d3dx9.h>
00034 #include <dxerr9.h>
00035 #include "OgreMemoryMacros.h"
00036 
00037 namespace Ogre 
00038 {
00039     /****************************************************************************************/
00040     D3D9Texture::D3D9Texture( const String& name, TextureType texType, IDirect3DDevice9 *pD3DDevice, TextureUsage usage )
00041     {
00042         // normal constructor
00043         this->_initMembers();
00044         // set the device and caps/formats
00045         this->_setDevice(pD3DDevice);
00046 
00047         mName = name;
00048         mTextureType = texType;
00049         mUsage = usage;
00050 
00051         if (this->getTextureType() == TEX_TYPE_CUBE_MAP)
00052             _constructCubeFaceNames(mName);
00053     }
00054     /****************************************************************************************/
00055     D3D9Texture::D3D9Texture( const String& name, TextureType texType, IDirect3DDevice9 *pD3DDevice, uint width, uint height, uint numMips, PixelFormat format, TextureUsage usage )
00056     {
00057         // this constructor is mainly used for RTT
00058         this->_initMembers();
00059         // set the device and caps/formats
00060         this->_setDevice(pD3DDevice);
00061 
00062         mName = name;
00063         mTextureType = texType;
00064         mUsage = usage;
00065         mNumMipMaps = numMips;
00066 
00067         if (this->getTextureType() == TEX_TYPE_CUBE_MAP)
00068             _constructCubeFaceNames(mName);
00069 
00070         this->_setSrcAttributes(width, height, 1, format);
00071         // if it's a render target we must 
00072         // create it right now, don't know why ???
00073         if (mUsage == TU_RENDERTARGET)
00074         {
00075             this->_createTex();
00076             mIsLoaded = true;
00077         }
00078     }
00079     /****************************************************************************************/
00080     D3D9Texture::~D3D9Texture()
00081     {
00082         if (this->isLoaded())
00083             unload();
00084         SAFE_RELEASE(mpD3D);
00085     }
00086     /****************************************************************************************/
00087     void D3D9Texture::blitImage(const Image& src, const Image::Rect imgRect, const Image::Rect texRect )
00088     {
00089         Except( Exception::UNIMPLEMENTED_FEATURE, "**** Blit image called but not implemented!!! ****", "D3D9Texture::blitImage" );
00090     }
00091     /****************************************************************************************/
00092     void D3D9Texture::blitToTexture( const Image &src, unsigned uStartX, unsigned uStartY )
00093     {
00094         Except( Exception::UNIMPLEMENTED_FEATURE, "**** Blit to texture called but not implemented!!! ****", "D3D9Texture::blitToTexture" );
00095     }
00096     /****************************************************************************************/
00097     void D3D9Texture::copyToTexture(Texture *target)
00098     {
00099         // check if this & target are the same format and type
00100         // blitting from or to cube textures is not supported yet
00101         if (target->getUsage() != this->getUsage() ||
00102             target->getTextureType() != this->getTextureType())
00103         {
00104             Except( Exception::ERR_INVALIDPARAMS, 
00105                     "Src. and dest. textures must be of same type and must have the same usage !!!", 
00106                     "D3D9Texture::copyToTexture" );
00107         }
00108 
00109         HRESULT hr;
00110         D3D9Texture *other;
00111         // get the target
00112         other = reinterpret_cast< D3D9Texture * >( target );
00113         // target rectangle (whole surface)
00114         RECT dstRC = {0, 0, other->getWidth(), other->getHeight()};
00115 
00116         // do it plain for normal texture
00117         if (this->getTextureType() == TEX_TYPE_2D)
00118         {
00119             // get our source surface
00120             IDirect3DSurface9 *pSrcSurface;
00121             if( FAILED( hr = mpNormTex->GetSurfaceLevel(0, &pSrcSurface) ) )
00122             {
00123                 String msg = DXGetErrorDescription9(hr);
00124                 Except( hr, "Couldn't blit : " + msg, "D3D9Texture::copyToTexture" );
00125             }
00126 
00127             // get our target surface
00128             IDirect3DSurface9 *pDstSurface;
00129             IDirect3DTexture9 *pOthTex = other->getNormTexture();
00130             if( FAILED( hr = pOthTex->GetSurfaceLevel(0, &pDstSurface) ) )
00131             {
00132                 String msg = DXGetErrorDescription9(hr);
00133                 Except( hr, "Couldn't blit : " + msg, "D3D9Texture::copyToTexture" );
00134                 SAFE_RELEASE(pSrcSurface);
00135             }
00136 
00137             // do the blit, it's called StretchRect in D3D9 :)
00138             if( FAILED( hr = mpDev->StretchRect( pSrcSurface, NULL, pDstSurface, &dstRC, D3DTEXF_NONE) ) )
00139             {
00140                 String msg = DXGetErrorDescription9(hr);
00141                 Except( hr, "Couldn't blit : " + msg, "D3D9Texture::copyToTexture" );
00142                 SAFE_RELEASE(pSrcSurface);
00143                 SAFE_RELEASE(pDstSurface);
00144             }
00145 
00146             // release temp. surfaces
00147             SAFE_RELEASE(pSrcSurface);
00148             SAFE_RELEASE(pDstSurface);
00149         }
00150         else if (this->getTextureType() == TEX_TYPE_CUBE_MAP)
00151         {
00152             // get the target cube texture
00153             IDirect3DCubeTexture9 *pOthTex = other->getCubeTexture();
00154             // blit to 6 cube faces
00155             for (size_t face = 0; face < 6; face++)
00156             {
00157                 // get our source surface
00158                 IDirect3DSurface9 *pSrcSurface;
00159                 if( FAILED( hr = mpCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, 0, &pSrcSurface) ) )
00160                 {
00161                     String msg = DXGetErrorDescription9(hr);
00162                     Except( hr, "Couldn't blit : " + msg, "D3D9Texture::copyToTexture" );
00163                 }
00164 
00165                 // get our target surface
00166                 IDirect3DSurface9 *pDstSurface;
00167                 if( FAILED( hr = pOthTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, 0, &pDstSurface) ) )
00168                 {
00169                     String msg = DXGetErrorDescription9(hr);
00170                     Except( hr, "Couldn't blit : " + msg, "D3D9Texture::copyToTexture" );
00171                     SAFE_RELEASE(pSrcSurface);
00172                 }
00173 
00174                 // do the blit, it's called StretchRect in D3D9 :)
00175                 if( FAILED( hr = mpDev->StretchRect( pSrcSurface, NULL, pDstSurface, &dstRC, D3DTEXF_NONE) ) )
00176                 {
00177                     String msg = DXGetErrorDescription9(hr);
00178                     Except( hr, "Couldn't blit : " + msg, "D3D9Texture::copyToTexture" );
00179                     SAFE_RELEASE(pSrcSurface);
00180                     SAFE_RELEASE(pDstSurface);
00181                 }
00182 
00183                 // release temp. surfaces
00184                 SAFE_RELEASE(pSrcSurface);
00185                 SAFE_RELEASE(pDstSurface);
00186             }
00187         }
00188         else
00189         {
00190             Except( Exception::UNIMPLEMENTED_FEATURE, 
00191                     "Copy to texture is implemented only for 2D and cube textures !!!", 
00192                     "D3D9Texture::copyToTexture" );
00193         }
00194     }
00195     /****************************************************************************************/
00196     void D3D9Texture::loadImage( const Image &img )
00197     {
00198         assert(this->getTextureType() == TEX_TYPE_1D || this->getTextureType() == TEX_TYPE_2D);
00199 
00200         Image tImage(img); // our temp image
00201         HRESULT hr = S_OK; // D3D9 methods result
00202 
00203         // we need src image info
00204         this->_setSrcAttributes(tImage.getWidth(), tImage.getHeight(), 1, tImage.getFormat());
00205         // create a blank texture
00206         this->_createNormTex();
00207         // set gamma prior to blitting
00208         Image::applyGamma(tImage.getData(), this->getGamma(), (uint)tImage.getSize(), tImage.getBPP());
00209         this->_blitImageToNormTex(tImage);
00210         mIsLoaded = true;
00211     }
00212     /****************************************************************************************/
00213     void D3D9Texture::load()
00214     {
00215         // unload if loaded
00216         if (this->isLoaded())
00217             unload();
00218         
00219         if (mUsage == TU_RENDERTARGET)
00220         {
00221             this->_createTex();
00222             mIsLoaded = true;
00223             return;
00224         }
00225 
00226         // load based on tex.type
00227         switch (this->getTextureType())
00228         {
00229         case TEX_TYPE_1D:
00230         case TEX_TYPE_2D:
00231             this->_loadNormTex();
00232             break;
00233         case TEX_TYPE_3D:
00234             this->_loadVolumeTex();
00235             break;
00236         case TEX_TYPE_CUBE_MAP:
00237             this->_loadCubeTex();
00238             break;
00239         default:
00240             Except( Exception::ERR_INTERNAL_ERROR, "Unknown texture type", "D3D9Texture::load" );
00241             this->_freeResources();
00242         }
00243 
00244     }
00245     /****************************************************************************************/
00246     void D3D9Texture::unload()
00247     {
00248         // unload if it's loaded
00249         if (this->isLoaded())
00250         {
00251             this->_freeResources();
00252             mIsLoaded = false;
00253         }
00254     }
00255     /****************************************************************************************/
00256     void D3D9Texture::_freeResources()
00257     {
00258         SAFE_RELEASE(mpTex);
00259         SAFE_RELEASE(mpNormTex);
00260         SAFE_RELEASE(mpCubeTex);
00261         SAFE_RELEASE(mpZBuff);
00262     }
00263     /****************************************************************************************/
00264     void D3D9Texture::_loadCubeTex()
00265     {
00266         assert(this->getTextureType() == TEX_TYPE_CUBE_MAP);
00267 
00268         // DDS load?
00269         if (getName().endsWith(".dds"))
00270         {
00271             // find & load resource data
00272             SDDataChunk chunk;
00273             TextureManager::getSingleton()._findResourceData(this->getName(), chunk);
00274 
00275             HRESULT hr = D3DXCreateCubeTextureFromFileInMemory(
00276                 mpDev,
00277                 chunk.getPtr(),
00278                 chunk.getSize(),
00279                 &mpCubeTex);
00280 
00281             if (FAILED(hr))
00282             {
00283                 Except( hr, "Can't create cube texture", "D3D9Texture::_loadCubeTex" );
00284                 this->_freeResources();
00285             }
00286 
00287             hr = mpCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&mpTex);
00288 
00289             if (FAILED(hr))
00290             {
00291                 Except( hr, "Can't get base texture", "D3D9Texture::_loadCubeTex" );
00292                 this->_freeResources();
00293             }
00294 
00295             D3DSURFACE_DESC texDesc;
00296             mpCubeTex->GetLevelDesc(0, &texDesc);
00297             // set src and dest attributes to the same, we can't know
00298             _setSrcAttributes(texDesc.Width, texDesc.Height, 1, _getPF(texDesc.Format));
00299             _setFinalAttributes(texDesc.Width, texDesc.Height, 1,  _getPF(texDesc.Format));
00300 
00301             
00302         }
00303         else
00304         {
00305 
00306             HRESULT hr = S_OK; // D3D9 methods result
00307             Image tImages[6]; // temp. images we'll use
00308 
00309             // we need src. image info so load first face
00310             // we assume that all faces are of the same dimensions
00311             // if they are not, they will be automatically 
00312             // resized when blitting
00313             tImages[0].load(this->_getCubeFaceName(0));
00314             this->_setSrcAttributes(tImages[0].getWidth(), tImages[0].getHeight(), 1, tImages[0].getFormat());
00315             // now create the texture
00316             this->_createCubeTex();
00317 
00318             // prepare faces
00319             for (size_t face = 0; face < 6; face++)
00320             {
00321                 // first face is already loaded
00322                 if (face > 0)
00323                     tImages[face].load(this->_getCubeFaceName(face)); // load the cube face
00324                 // set gamma prior to blitting
00325                 Image::applyGamma(
00326                         tImages[face].getData(), 
00327                         this->getGamma(), 
00328                         (uint)tImages[face].getSize(), 
00329                         tImages[face].getBPP());
00330             }
00331             // blit them all :(
00332             this->_blitImagesToCubeTex(tImages);
00333         }
00334         // say IT'S loaded loud ;) 
00335         mIsLoaded = true;
00336     }
00337     /****************************************************************************************/
00338     void D3D9Texture::_loadVolumeTex()
00339     {
00340         assert(this->getTextureType() == TEX_TYPE_3D);
00341 
00342         // find & load resource data
00343         SDDataChunk chunk;
00344         TextureManager::getSingleton()._findResourceData(this->getName(), chunk);
00345 
00346         HRESULT hr = D3DXCreateVolumeTextureFromFileInMemory(
00347             mpDev,
00348             chunk.getPtr(),
00349             chunk.getSize(),
00350             &mpVolumeTex);
00351 
00352         if (FAILED(hr))
00353         {
00354             Except(Exception::ERR_INTERNAL_ERROR, 
00355                 "Unable to load volume texture from " + this->getName(),
00356                 "D3D9Texture::_loadVolumeTex");
00357         }
00358 
00359         hr = mpVolumeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&mpTex);
00360 
00361         if (FAILED(hr))
00362         {
00363             Except( hr, "Can't get base texture", "D3D9Texture::_loadVolumeTex" );
00364             this->_freeResources();
00365         }
00366 
00367         D3DVOLUME_DESC texDesc;
00368         hr = mpVolumeTex->GetLevelDesc(0, &texDesc);
00369 
00370         // set src and dest attributes to the same, we can't know
00371         _setSrcAttributes(texDesc.Width, texDesc.Height, texDesc.Depth, _getPF(texDesc.Format));
00372         _setFinalAttributes(texDesc.Width, texDesc.Height, texDesc.Depth, _getPF(texDesc.Format));
00373         
00374         mIsLoaded = true;
00375     }
00376     /****************************************************************************************/
00377     void D3D9Texture::_loadNormTex()
00378     {
00379         assert(this->getTextureType() == TEX_TYPE_1D || this->getTextureType() == TEX_TYPE_2D);
00380 
00381         // Use D3DX
00382         // find & load resource data
00383         SDDataChunk chunk;
00384         TextureManager::getSingleton()._findResourceData(this->getName(), chunk);
00385 
00386         HRESULT hr = D3DXCreateTextureFromFileInMemory(
00387             mpDev,
00388             chunk.getPtr(),
00389             chunk.getSize(),
00390             &mpNormTex);
00391 
00392         if (FAILED(hr))
00393         {
00394             Except(Exception::ERR_INTERNAL_ERROR, 
00395                 "Unable to load texture from " + this->getName(),
00396                 "D3D9Texture::_loadNormTex");
00397         }
00398 
00399         hr = mpNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&mpTex);
00400 
00401         if (FAILED(hr))
00402         {
00403             Except( hr, "Can't get base texture", "D3D9Texture::_loadNormTex" );
00404             this->_freeResources();
00405         }
00406 
00407         D3DSURFACE_DESC texDesc;
00408         mpNormTex->GetLevelDesc(0, &texDesc);
00409         // set src and dest attributes to the same, we can't know
00410         _setSrcAttributes(texDesc.Width, texDesc.Height, 1, _getPF(texDesc.Format));
00411         _setFinalAttributes(texDesc.Width, texDesc.Height, 1, _getPF(texDesc.Format));
00412         
00413         /*        
00414         Image tImage; // temp. image we'll use
00415         HRESULT hr = S_OK; // D3D9 methods result
00416 
00417         // we need src image info
00418         tImage.load(this->getName());
00419         this->_setSrcAttributes(tImage.getWidth(), tImage.getHeight(), tImage.getFormat());
00420         // now create it
00421         this->_createNormTex();
00422         // set gamma prior to blitting
00423         Image::applyGamma(tImage.getData(), this->getGamma(), (uint)tImage.getSize(), tImage.getBPP());
00424         // make the BLT !!!
00425         this->_blitImageToNormTex(tImage);
00426         // say IT'S loaded loud ;) 
00427         */
00428         mIsLoaded = true;
00429     }
00430     /****************************************************************************************/
00431     void D3D9Texture::_createTex()
00432     {
00433         // if we are there then the source image dim. and format must already be set !!!
00434         assert(mSrcWidth > 0 || mSrcHeight > 0);
00435 
00436         // load based on tex.type
00437         switch (this->getTextureType())
00438         {
00439         case TEX_TYPE_1D:
00440         case TEX_TYPE_2D:
00441             this->_createNormTex();
00442             break;
00443         case TEX_TYPE_CUBE_MAP:
00444             this->_createCubeTex();
00445             break;
00446         default:
00447             Except( Exception::ERR_INTERNAL_ERROR, "Unknown texture type", "D3D9Texture::_createTex" );
00448             this->_freeResources();
00449         }
00450     }
00451     /****************************************************************************************/
00452     void D3D9Texture::_createNormTex()
00453     {
00454         // we must have those defined here
00455         assert(mSrcWidth > 0 || mSrcHeight > 0);
00456 
00457         // determine wich D3D9 pixel format we'll use
00458         HRESULT hr;
00459         D3DFORMAT d3dPF = (mUsage == TU_RENDERTARGET) ? mBBPixelFormat : this->_chooseD3DFormat();
00460 
00461         // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
00462         DWORD usage = (mUsage == TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
00463         UINT numMips = (mNumMipMaps ? mNumMipMaps : 1);
00464         // check if mip maps are supported on hardware
00465         if (mDevCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
00466         {
00467             // use auto.gen. if available
00468             if (this->_canAutoGenMipMaps(usage, D3DRTYPE_TEXTURE, d3dPF))
00469             {
00470                 usage |= D3DUSAGE_AUTOGENMIPMAP;
00471                 numMips = 0;
00472             }
00473             else
00474             {
00475                 if (mUsage != TU_RENDERTARGET)
00476                 {
00477                     // we must create a temp. texture in SYSTEM MEMORY if no auto gen. mip map is present
00478                     hr = D3DXCreateTexture( 
00479                         mpDev,                              // device
00480                         mSrcWidth,                          // width
00481                         mSrcHeight,                         // height
00482                         numMips,                            // number of mip map levels
00483                         usage,                              // usage
00484                         d3dPF,                              // pixel format
00485                         D3DPOOL_SYSTEMMEM,                  // memory pool
00486                         &mpTmpNormTex);                     // data pointer
00487                     // check result and except if failed
00488                     if (FAILED(hr))
00489                     {
00490                         Except( hr, "Error creating texture", "D3D9Texture::_createNormTex" );
00491                         this->_freeResources();
00492                     }
00493                 }
00494             }
00495         }
00496         else
00497         {
00498             // device don't support mip maps ???
00499             mNumMipMaps = 0;
00500             numMips = 1;
00501         }
00502 
00503         // create the texture
00504         hr = D3DXCreateTexture( 
00505                 mpDev,                              // device
00506                 mSrcWidth,                          // width
00507                 mSrcHeight,                         // height
00508                 numMips,                            // number of mip map levels
00509                 usage,                              // usage
00510                 d3dPF,                              // pixel format
00511                 D3DPOOL_DEFAULT,                    // memory pool
00512                 &mpNormTex);                        // data pointer
00513         // check result and except if failed
00514         if (FAILED(hr))
00515         {
00516             Except( hr, "Error creating texture", "D3D9Texture::_createNormTex" );
00517             this->_freeResources();
00518         }
00519 
00520         // set final tex. attributes from tex. description
00521         // they may differ from the source image !!!
00522         D3DSURFACE_DESC desc;
00523         hr = mpNormTex->GetLevelDesc(0, &desc);
00524         if (FAILED(hr))
00525         {
00526             Except( hr, "Can't get texture description", "D3D9Texture::_createNormTex" );
00527             this->_freeResources();
00528         }
00529         this->_setFinalAttributes(desc.Width, desc.Height, 1, this->_getPF(desc.Format));
00530         
00531         // set the base texture we'll use in the render system
00532         hr = mpNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&mpTex);
00533         if (FAILED(hr))
00534         {
00535             Except( hr, "Can't get base texture", "D3D9Texture::_createNormTex" );
00536             this->_freeResources();
00537         }
00538         
00539         // create a depth stencil if this is a render target
00540         if (mUsage == TU_RENDERTARGET)
00541             this->_createDepthStencil();
00542 
00543     }
00544     /****************************************************************************************/
00545     void D3D9Texture::_createCubeTex()
00546     {
00547         // we must have those defined here
00548         assert(mSrcWidth > 0 || mSrcHeight > 0);
00549 
00550         // determine wich D3D9 pixel format we'll use
00551         HRESULT hr;
00552         D3DFORMAT d3dPF = (mUsage == TU_RENDERTARGET) ? mBBPixelFormat : this->_chooseD3DFormat();
00553 
00554         // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
00555         DWORD usage = (mUsage == TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
00556         UINT numMips = (mNumMipMaps ? mNumMipMaps : 1);
00557         // check if mip map cube textures are supported
00558         if (mDevCaps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
00559         {
00560             // use auto.gen. if available
00561             if (this->_canAutoGenMipMaps(usage, D3DRTYPE_CUBETEXTURE, d3dPF))
00562             {
00563                 usage |= D3DUSAGE_AUTOGENMIPMAP;
00564                 numMips = 0;
00565             }
00566             else
00567             {
00568                 if (mUsage != TU_RENDERTARGET)
00569                 {
00570                     // we must create a temp. texture in SYSTEM MEMORY if no auto gen. mip map is present
00571                     hr = D3DXCreateCubeTexture( 
00572                         mpDev,                              // device
00573                         mSrcWidth,                          // dimension
00574                         numMips,                            // number of mip map levels
00575                         usage,                              // usage
00576                         d3dPF,                              // pixel format
00577                         D3DPOOL_SYSTEMMEM,                  // memory pool
00578                         &mpTmpCubeTex);                     // data pointer
00579                     // check result and except if failed
00580                     if (FAILED(hr))
00581                     {
00582                         Except( hr, "Error creating texture", "D3D9Texture::_createCubeTex" );
00583                         this->_freeResources();
00584                     }
00585                 }
00586             }
00587         }
00588         else
00589         {
00590             // no mip map support for this kind of textures :(
00591             mNumMipMaps = 0;
00592             numMips = 1;
00593         }
00594 
00595         // create the texture
00596         hr = D3DXCreateCubeTexture( 
00597                 mpDev,                              // device
00598                 mSrcWidth,                          // dimension
00599                 numMips,                            // number of mip map levels
00600                 usage,                              // usage
00601                 d3dPF,                              // pixel format
00602                 D3DPOOL_DEFAULT,                    // memory pool
00603                 &mpCubeTex);                        // data pointer
00604         // check result and except if failed
00605         if (FAILED(hr))
00606         {
00607             Except( hr, "Error creating texture", "D3D9Texture::_createCubeTex" );
00608             this->_freeResources();
00609         }
00610 
00611         // set final tex. attributes from tex. description
00612         // they may differ from the source image !!!
00613         D3DSURFACE_DESC desc;
00614         hr = mpCubeTex->GetLevelDesc(0, &desc);
00615         if (FAILED(hr))
00616         {
00617             Except( hr, "Can't get texture description", "D3D9Texture::_createCubeTex" );
00618             this->_freeResources();
00619         }
00620         this->_setFinalAttributes(desc.Width, desc.Height, 1, this->_getPF(desc.Format));
00621 
00622         // set the base texture we'll use in the render system
00623         hr = mpCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&mpTex);
00624         if (FAILED(hr))
00625         {
00626             Except( hr, "Can't get base texture", "D3D9Texture::_createCubeTex" );
00627             this->_freeResources();
00628         }
00629         
00630         // create a depth stencil if this is a render target
00631         if (mUsage == TU_RENDERTARGET)
00632             this->_createDepthStencil();
00633 
00634     }
00635     /****************************************************************************************/
00636     void D3D9Texture::_initMembers()
00637     {
00638         mpDev = NULL;
00639         mpD3D = NULL;
00640         mpNormTex = NULL;
00641         mpCubeTex = NULL;
00642         mpZBuff = NULL;
00643         mpTex = NULL;
00644 
00645         mpTmpNormTex = NULL;
00646         mpTmpCubeTex = NULL;
00647 
00648         for (size_t i = 0; i < 6; ++i)
00649             mCubeFaceNames[i] = "";
00650 
00651         mWidth = mHeight = mSrcWidth = mSrcHeight = 0;
00652         mIsLoaded = false;
00653     }
00654     /****************************************************************************************/
00655     void D3D9Texture::_setDevice(IDirect3DDevice9 *pDev)
00656     { 
00657         assert(pDev);
00658         mpDev = pDev;
00659         HRESULT hr;
00660 
00661         // get device caps
00662         hr = mpDev->GetDeviceCaps(&mDevCaps);
00663         if (FAILED(hr))
00664             Except( Exception::ERR_INTERNAL_ERROR, "Can't get device description", "D3D9Texture::_setDevice" );
00665 
00666         // get D3D pointer
00667         hr = mpDev->GetDirect3D(&mpD3D);
00668         if (FAILED(hr))
00669             Except( hr, "Failed to get D3D9 pointer", "D3D9Texture::_setDevice" );
00670 
00671         // get our device creation parameters
00672         hr = mpDev->GetCreationParameters(&mDevCreParams);
00673         if (FAILED(hr))
00674             Except( hr, "Failed to get D3D9 device creation parameters", "D3D9Texture::_setDevice" );
00675 
00676         // get our back buffer pixel format
00677         IDirect3DSurface9 *pSrf;
00678         D3DSURFACE_DESC srfDesc;
00679         hr = mpDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSrf);
00680         if (FAILED(hr))
00681             Except( hr, "Failed to get D3D9 device pixel format", "D3D9Texture::_setDevice" );
00682 
00683         hr = pSrf->GetDesc(&srfDesc);
00684         if (FAILED(hr))
00685         {
00686             Except( hr, "Failed to get D3D9 device pixel format", "D3D9Texture::_setDevice" );
00687             SAFE_RELEASE(pSrf);
00688         }
00689 
00690         mBBPixelFormat = srfDesc.Format;
00691         SAFE_RELEASE(pSrf);
00692     }
00693     /****************************************************************************************/
00694     void D3D9Texture::_constructCubeFaceNames(const String& name)
00695     {
00696         // the suffixes
00697         static const String suffixes[6] = {"_rt", "_lf", "_up", "_dn", "_fr", "_bk"};
00698         size_t pos = -1;
00699 
00700         String ext; // the extension
00701         String baseName; // the base name
00702         String fakeName = name; // the 'fake' name, temp. holder
00703 
00704         // first find the base name
00705         pos = fakeName.find_last_of(".");
00706         if (pos == -1)
00707         {
00708             Except( Exception::ERR_INTERNAL_ERROR, "Invalid cube texture base name", "D3D9Texture::_constructCubeFaceNames" );
00709             this->_freeResources();
00710         }
00711 
00712         baseName = fakeName.substr(0, pos);
00713         ext = fakeName.substr(pos);
00714 
00715         // construct the full 6 faces file names from the baseName, suffixes and extension
00716         for (size_t i = 0; i < 6; ++i)
00717             mCubeFaceNames[i] = baseName + suffixes[i] + ext;
00718     }
00719     /****************************************************************************************/
00720     void D3D9Texture::_setFinalAttributes(unsigned long width, unsigned long height, 
00721         unsigned long depth, PixelFormat format)
00722     { 
00723         // set target texture attributes
00724         mHeight = height; 
00725         mWidth = width; 
00726         mDepth = depth;
00727         mFormat = format; 
00728 
00729         // Update size (the final size, not including temp space)
00730         // this is needed in Resource class
00731         unsigned short bytesPerPixel = mFinalBpp >> 3;
00732         if( !mHasAlpha && mFinalBpp == 32 )
00733             bytesPerPixel--;
00734         mSize = mWidth * mHeight * mDepth * bytesPerPixel 
00735             * (mTextureType == TEX_TYPE_CUBE_MAP)? 6 : 1;
00736 
00737         // say to the world what we are doing
00738         if (mWidth != mSrcWidth ||
00739             mHeight != mSrcHeight)
00740         {
00741             LogManager::getSingleton().logMessage("D3D9 : ***** Dimensions altered by the render system");
00742             LogManager::getSingleton().logMessage("D3D9 : ***** Source image dimensions : " + StringConverter::toString(mSrcWidth) + "x" + StringConverter::toString(mSrcHeight));
00743             LogManager::getSingleton().logMessage("D3D9 : ***** Texture dimensions : " + StringConverter::toString(mWidth) + "x" + StringConverter::toString(mHeight));
00744         }
00745     }
00746     /****************************************************************************************/
00747     void D3D9Texture::_setSrcAttributes(unsigned long width, unsigned long height, 
00748         unsigned long depth, PixelFormat format)
00749     { 
00750         // set source image attributes
00751         mSrcWidth = width; 
00752         mSrcHeight = height; 
00753         mSrcBpp = _getPFBpp(format); 
00754         mHasAlpha = Image::formatHasAlpha(format); 
00755         // say to the world what we are doing
00756         switch (this->getTextureType())
00757         {
00758         case TEX_TYPE_1D:
00759             if (mUsage == TU_RENDERTARGET)
00760                 LogManager::getSingleton().logMessage("D3D9 : Creating 1D RenderTarget, name : '" + this->getName() + "' with " + StringConverter::toString(mNumMipMaps) + " mip map levels");
00761             else
00762                 LogManager::getSingleton().logMessage("D3D9 : Loading 1D Texture, image name : '" + this->getName() + "' with " + StringConverter::toString(mNumMipMaps) + " mip map levels");
00763             break;
00764         case TEX_TYPE_2D:
00765             if (mUsage == TU_RENDERTARGET)
00766                 LogManager::getSingleton().logMessage("D3D9 : Creating 2D RenderTarget, name : '" + this->getName() + "' with " + StringConverter::toString(mNumMipMaps) + " mip map levels");
00767             else
00768                 LogManager::getSingleton().logMessage("D3D9 : Loading 2D Texture, image name : '" + this->getName() + "' with " + StringConverter::toString(mNumMipMaps) + " mip map levels");
00769             break;
00770         case TEX_TYPE_3D:
00771             if (mUsage == TU_RENDERTARGET)
00772                 LogManager::getSingleton().logMessage("D3D9 : Creating 3D RenderTarget, name : '" + this->getName() + "' with " + StringConverter::toString(mNumMipMaps) + " mip map levels");
00773             else
00774                 LogManager::getSingleton().logMessage("D3D9 : Loading 3D Texture, image name : '" + this->getName() + "' with " + StringConverter::toString(mNumMipMaps) + " mip map levels");
00775             break;
00776         case TEX_TYPE_CUBE_MAP:
00777             if (mUsage == TU_RENDERTARGET)
00778                 LogManager::getSingleton().logMessage("D3D9 : Creating Cube map RenderTarget, name : '" + this->getName() + "' with " + StringConverter::toString(mNumMipMaps) + " mip map levels");
00779             else
00780                 LogManager::getSingleton().logMessage("D3D9 : Loading Cube Texture, base image name : '" + this->getName() + "' with " + StringConverter::toString(mNumMipMaps) + " mip map levels");
00781             break;
00782         default:
00783             Except( Exception::ERR_INTERNAL_ERROR, "Unknown texture type", "D3D9Texture::_createTex" );
00784             this->_freeResources();
00785         }
00786     }
00787     /****************************************************************************************/
00788     D3DTEXTUREFILTERTYPE D3D9Texture::_getBestFilterMethod()
00789     {
00790         // those MUST be initialized !!!
00791         assert(mpDev);
00792         assert(mpD3D);
00793         assert(mpTex);
00794 
00795         // TODO : do it really :)
00796         return D3DTEXF_POINT;
00797     }
00798     /****************************************************************************************/
00799     bool D3D9Texture::_canAutoGenMipMaps(DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat)
00800     {
00801         // those MUST be initialized !!!
00802         assert(mpDev);
00803         assert(mpD3D);
00804 
00805         if (mDevCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
00806         {
00807             HRESULT hr;
00808             // check for auto gen. mip maps support
00809             hr = mpD3D->CheckDeviceFormat(
00810                     mDevCreParams.AdapterOrdinal, 
00811                     mDevCreParams.DeviceType, 
00812                     mBBPixelFormat, 
00813                     srcUsage | D3DUSAGE_AUTOGENMIPMAP,
00814                     srcType,
00815                     srcFormat);
00816             // this HR could a SUCCES
00817             // but mip maps will not be generated
00818             if (hr == D3D_OK)
00819                 return true;
00820             else
00821                 return false;
00822         }
00823         else
00824             return false;
00825     }
00826     /****************************************************************************************/
00827     void D3D9Texture::_getColorMasks(D3DFORMAT format, DWORD *pdwRed, DWORD *pdwGreen, DWORD *pdwBlue, DWORD *pdwAlpha, DWORD *pdwRGBBitCount)
00828     {
00829         // we choose the format of the D3D texture so check only for our pf types...
00830         switch (format)
00831         {
00832         case D3DFMT_X8R8G8B8:
00833             *pdwRed = 0x00FF0000; *pdwGreen = 0x0000FF00; *pdwBlue = 0x000000FF; *pdwAlpha = 0x00000000;
00834             *pdwRGBBitCount = 32;
00835             break;
00836         case D3DFMT_R8G8B8:
00837             *pdwRed = 0x00FF0000; *pdwGreen = 0x0000FF00; *pdwBlue = 0x000000FF; *pdwAlpha = 0x00000000;
00838             *pdwRGBBitCount = 24;
00839             break;
00840         case D3DFMT_A8R8G8B8:
00841             *pdwRed = 0x00FF0000; *pdwGreen = 0x0000FF00; *pdwBlue = 0x000000FF; *pdwAlpha = 0xFF000000;
00842             *pdwRGBBitCount = 32;
00843             break;
00844         case D3DFMT_X1R5G5B5:
00845             *pdwRed = 0x00007C00; *pdwGreen = 0x000003E0; *pdwBlue = 0x0000001F; *pdwAlpha = 0x00000000;
00846             *pdwRGBBitCount = 16;
00847             break;
00848         case D3DFMT_R5G6B5:
00849             *pdwRed = 0x0000F800; *pdwGreen = 0x000007E0; *pdwBlue = 0x0000001F; *pdwAlpha = 0x00000000;
00850             *pdwRGBBitCount = 16;
00851             break;
00852         case D3DFMT_A4R4G4B4:
00853             *pdwRed = 0x00000F00; *pdwGreen = 0x000000F0; *pdwBlue = 0x0000000F; *pdwAlpha = 0x0000F000;
00854             *pdwRGBBitCount = 16;
00855             break;
00856         default:
00857             Except( Exception::ERR_INTERNAL_ERROR, "Unknown D3D pixel format, this should not happen !!!", "D3D9Texture::_getColorMasks" );
00858         }
00859     }
00860     /****************************************************************************************/
00861     void D3D9Texture::_copyMemoryToSurface(const unsigned char *pBuffer, IDirect3DSurface9 *pSurface)
00862     {
00863         assert(pBuffer);
00864         assert(pSurface);
00865         // Copy the image from the buffer to the temporary surface.
00866         // We have to do our own colour conversion here since we don't 
00867         // have a DC to do it for us
00868         // NOTE - only non-palettised surfaces supported for now
00869         HRESULT hr;
00870         D3DSURFACE_DESC desc;
00871         D3DLOCKED_RECT rect;
00872         BYTE *pSurf8;
00873         BYTE *pBuf8;
00874         DWORD data32;
00875         DWORD out32;
00876         unsigned iRow, iCol;
00877         // NOTE - dimensions of surface may differ from buffer
00878         // dimensions (e.g. power of 2 or square adjustments)
00879         // Lock surface
00880         pSurface->GetDesc(&desc);
00881         DWORD aMask, rMask, gMask, bMask, rgbBitCount;
00882         this->_getColorMasks(desc.Format, &rMask, &gMask, &bMask, &aMask, &rgbBitCount);
00883         // lock our surface to acces raw memory
00884         if( FAILED( hr = pSurface->LockRect(&rect, NULL, D3DLOCK_NOSYSLOCK) ) )
00885         {
00886             Except( hr, "Unable to lock temp texture surface", "D3D9Texture::_copyMemoryToSurface" );
00887             this->_freeResources();
00888             SAFE_RELEASE(pSurface);
00889         }
00890         else
00891             pBuf8 = (BYTE*)pBuffer;
00892         // loop through data and do conv.
00893         for( iRow = 0; iRow < mSrcHeight; iRow++ )
00894         {
00895             pSurf8 = (BYTE*)rect.pBits + (iRow * rect.Pitch);
00896             for( iCol = 0; iCol < mSrcWidth; iCol++ )
00897             {
00898                 // Read RGBA values from buffer
00899                 data32 = 0;
00900                 if( mSrcBpp >= 24 )
00901                 {
00902                     // Data in buffer is in RGB(A) format
00903                     // Read into a 32-bit structure
00904                     // Uses bytes for 24-bit compatibility
00905                     // NOTE: buffer is big-endian
00906                     data32 |= *pBuf8++ << 24;
00907                     data32 |= *pBuf8++ << 16;
00908                     data32 |= *pBuf8++ << 8;
00909                 }
00910                 else if( mSrcBpp == 8 ) // Greyscale, not palettised (palettised NOT supported)
00911                 {
00912                     // Duplicate same greyscale value across R,G,B
00913                     data32 |= *pBuf8 << 24;
00914                     data32 |= *pBuf8 << 16;
00915                     data32 |= *pBuf8++ << 8;
00916                 }
00917                 // check for alpha
00918                 if( mHasAlpha )
00919                     data32 |= *pBuf8++;
00920                 else
00921                     data32 |= 0xFF; // Set opaque
00922                 // Write RGBA values to surface
00923                 // Data in surface can be in varying formats
00924                 // Use bit concersion function
00925                 // NOTE: we use a 32-bit value to manipulate
00926                 // Will be reduced to size later
00927 
00928                 // Red
00929                 out32 = Bitwise::convertBitPattern<DWORD, DWORD>( data32, 0xFF000000, rMask );
00930                 // Green
00931                 out32 |= Bitwise::convertBitPattern<DWORD, DWORD>( data32, 0x00FF0000, gMask );
00932                 // Blue
00933                 out32 |= Bitwise::convertBitPattern<DWORD, DWORD>( data32, 0x0000FF00, bMask );
00934                 // Alpha
00935                 if( aMask > 0 )
00936                 {
00937                     out32 |= Bitwise::convertBitPattern<DWORD, DWORD>( data32, 0x000000FF, aMask );
00938                 }
00939                 // Assign results to surface pixel
00940                 // Write up to 4 bytes
00941                 // Surfaces are little-endian (low byte first)
00942                 if( rgbBitCount >= 8 )
00943                     *pSurf8++ = (BYTE)out32;
00944                 if( rgbBitCount >= 16 )
00945                     *pSurf8++ = (BYTE)(out32 >> 8);
00946                 if( rgbBitCount >= 24 )
00947                     *pSurf8++ = (BYTE)(out32 >> 16);
00948                 if( rgbBitCount >= 32 )
00949                     *pSurf8++ = (BYTE)(out32 >> 24);
00950             } // for( iCol...
00951         } // for( iRow...
00952         // unlock the surface
00953         pSurface->UnlockRect();
00954     }
00955     /****************************************************************************************/
00956     void D3D9Texture::_blitImageToNormTex(const Image &srcImage)
00957     {
00958         HRESULT hr;
00959         D3DFORMAT srcFormat = this->_getPF(srcImage.getFormat());
00960         D3DFORMAT dstFormat = _chooseD3DFormat();
00961         RECT tmpDataRect = {0, 0, srcImage.getWidth(), srcImage.getHeight()}; // the rectangle representing the src. image dim.
00962 
00963         // this surface will hold our temp conversion image
00964         // We need this in all cases because we can't lock 
00965         // the main texture surfaces in all cards
00966         // Also , this cannot be the temp texture because we'd like D3DX to resize it for us
00967         // with the D3DxLoadSurfaceFromSurface
00968         IDirect3DSurface9 *pSrcSurface = NULL;
00969         hr = mpDev->CreateOffscreenPlainSurface( 
00970                         srcImage.getWidth(),
00971                         srcImage.getHeight(),
00972                         dstFormat, 
00973                         D3DPOOL_SCRATCH, 
00974                         &pSrcSurface, 
00975                         NULL);
00976         // check result and except if failed
00977         if (FAILED(hr))
00978         {
00979             this->_freeResources();
00980             Except( hr, "Error loading surface from memory", "D3D9Texture::_blitImageToTexture" );
00981         }
00982         
00983         // copy the buffer to our surface, 
00984         // _copyMemoryToSurface will do color conversion and flipping
00985         this->_copyMemoryToSurface(srcImage.getData(), pSrcSurface);
00986 
00987         // Now we need to copy the source surface (where our image is) to the texture
00988         // This will be a temp texture for s/w filtering and the final one for h/w filtering
00989         // This will perform any size conversion (inc stretching)
00990         IDirect3DSurface9 *pDstSurface; 
00991         if (mpTmpNormTex)
00992         {
00993             // s/w mipmaps, use temp texture
00994             hr = mpTmpNormTex->GetSurfaceLevel(0, &pDstSurface);
00995         }
00996         else
00997         {
00998             // h/w mipmaps, use the final texture
00999             hr = mpNormTex->GetSurfaceLevel(0, &pDstSurface);
01000         }
01001 
01002         // check result and except if failed
01003         if (FAILED(hr))
01004         {
01005             SAFE_RELEASE(pSrcSurface);
01006             this->_freeResources();
01007             Except( hr, "Error getting level 0 surface from dest. texture", "D3D9Texture::_blitImageToTexture" );
01008         }
01009 
01010         // copy surfaces
01011         hr = D3DXLoadSurfaceFromSurface(pDstSurface, NULL, NULL, pSrcSurface, NULL, NULL, D3DX_DEFAULT, 0);
01012         // check result and except if failed
01013         if (FAILED(hr))
01014         {
01015             SAFE_RELEASE(pSrcSurface);
01016             SAFE_RELEASE(pDstSurface);
01017             this->_freeResources();
01018             Except( hr, "Error copying original surface to texture", "D3D9Texture::_blitImageToTexture" );
01019         }
01020 
01021         if (mpTmpNormTex)
01022         {
01023             // Software filtering
01024             // Now update the texture & filter the results
01025             // we will use D3DX to create the mip map levels
01026             if( FAILED( hr = D3DXFilterTexture( mpTmpNormTex, NULL, D3DX_DEFAULT, D3DX_DEFAULT ) ) )
01027             {
01028                 SAFE_RELEASE(pSrcSurface);
01029                 SAFE_RELEASE(pDstSurface);
01030                 this->_freeResources();
01031                 Except( hr, "Failed to filter texture (generate mip maps)", "D3D9Texture::_blitImageToTexture" );
01032             }
01033             if( FAILED( hr = mpDev->UpdateTexture( mpTmpNormTex, mpNormTex ) ) )
01034             {
01035                 SAFE_RELEASE(pSrcSurface);
01036                 SAFE_RELEASE(pDstSurface);
01037                 this->_freeResources();
01038                 Except( hr, "Failed to update texture", "D3D9Texture::_blitImageToTexture" );
01039             }
01040         }
01041         else
01042         {
01043             // Hardware mipmapping
01044             // use best filtering method supported by hardware
01045             hr = mpTex->SetAutoGenFilterType(_getBestFilterMethod());
01046             if (FAILED(hr))
01047             {
01048                 SAFE_RELEASE(pSrcSurface);
01049                 SAFE_RELEASE(pDstSurface);
01050                 this->_freeResources();
01051                 Except( hr, "Error generating mip maps", "D3D9Texture::_blitImageToNormTex" );
01052             }
01053             mpNormTex->GenerateMipSubLevels();
01054 
01055             
01056         }
01057 
01058         SAFE_RELEASE(pDstSurface);
01059         SAFE_RELEASE(pSrcSurface);
01060         SAFE_RELEASE(mpTmpNormTex);
01061     }
01062     /****************************************************************************************/
01063     void D3D9Texture::_blitImagesToCubeTex(const Image srcImages[])
01064     {
01065         HRESULT hr;
01066         D3DFORMAT dstFormat = _chooseD3DFormat();
01067 
01068         // we must loop through all 6 cube map faces :(
01069         for (size_t face = 0; face < 6; face++)
01070         {
01071             D3DFORMAT srcFormat = this->_getPF(srcImages[face].getFormat());
01072             RECT tmpDataRect = {0, 0, srcImages[face].getWidth(), srcImages[face].getHeight()}; // the rectangle representing the src. image dim.
01073 
01074             // this surface will hold our temp conversion image
01075             IDirect3DSurface9 *pSrcSurface = NULL;
01076             // We need this in all cases because we can't lock 
01077             // the main texture surfaces in all cards
01078             // Also , this cannot be the temp texture because we'd like D3DX to resize it for us
01079             // with the D3DxLoadSurfaceFromSurface
01080             hr = mpDev->CreateOffscreenPlainSurface( 
01081                             srcImages[face].getWidth(), 
01082                             srcImages[face].getHeight(), 
01083                             dstFormat, 
01084                             D3DPOOL_SCRATCH, 
01085                             &pSrcSurface, 
01086                             NULL);
01087             // check result and except if failed
01088             if (FAILED(hr))
01089             {
01090                 Except( hr, "Error loading surface from memory", "D3D9Texture::_blitImagesToCubeTex" );
01091                 this->_freeResources();
01092             }
01093 
01094             // don't know why but cube textures don't require fliping
01095             // _copyMemoryToSurface flips all around x, so we'll flip the
01096             // src.image first, then 'reflip' it :(, and we need a temp. image for this :(
01097             Image tmpImg(srcImages[face]);
01098             //tmpImg.flipAroundX();
01099             // copy the buffer to our surface, 
01100             // _copyMemoryToSurface will do color conversion and flipping
01101             this->_copyMemoryToSurface(tmpImg.getData(), pSrcSurface);
01102 
01103             // Now we need to copy the source surface (where our image is) to 
01104             // either the the temp. texture level 0 surface (for s/w mipmaps)
01105             // or the final texture (for h/w mipmaps)
01106             IDirect3DSurface9 *pDstSurface; 
01107             if (mpTmpCubeTex)
01108             {
01109                 // copy into temp
01110                 hr = mpTmpCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, 0, &pDstSurface);
01111             }
01112             else
01113             {
01114                 // copy into temp
01115                 hr = mpCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, 0, &pDstSurface);
01116             }
01117             // check result and except if failed
01118             if (FAILED(hr))
01119             {
01120                 Except( hr, "Error getting level dest cube map surface", "D3D9Texture::_blitImagesToCubeTex" );
01121                 SAFE_RELEASE(pSrcSurface);
01122                 this->_freeResources();
01123             }
01124 
01125             // load the surface with an in memory buffer
01126             hr = D3DXLoadSurfaceFromSurface(pDstSurface, NULL, NULL, pSrcSurface, NULL, NULL, D3DX_DEFAULT, 0);
01127             // check result and except if failed
01128             if (FAILED(hr))
01129             {
01130                 Except( hr, "Error loading in temporary surface", "D3D9Texture::_blitImagesToCubeTex" );
01131                 SAFE_RELEASE(pSrcSurface);
01132                 SAFE_RELEASE(pDstSurface);
01133                 this->_freeResources();
01134             }
01135 
01136             SAFE_RELEASE(pDstSurface);
01137             SAFE_RELEASE(pSrcSurface);
01138         }
01139 
01140         // After doing all the faces, we generate mipmaps
01141         // For s/w mipmaps this involves an extra copying step
01142         if (mpTmpCubeTex)
01143         {
01144             // Filter
01145             if( FAILED( hr = D3DXFilterTexture( mpTmpCubeTex, NULL, D3DX_DEFAULT, D3DX_DEFAULT ) ) )
01146             {
01147                 this->_freeResources();
01148                 Except( hr, "Failed to filter texture (generate mip maps)", "D3D9Texture::_blitImageToCubeTex" );
01149             }
01150             // Update main texture
01151             if( FAILED( hr = mpDev->UpdateTexture( mpTmpCubeTex, mpCubeTex ) ) )
01152             {
01153                 this->_freeResources();
01154                 Except( hr, "Failed to update texture", "D3D9Texture::_blitImageToCubeTex" );
01155             }
01156         }
01157         else
01158         {
01159             // Hardware filter
01160             // use best filtering method supported by hardware
01161             hr = mpTex->SetAutoGenFilterType(_getBestFilterMethod());
01162             if (FAILED(hr))
01163             {
01164                 this->_freeResources();
01165                 Except( hr, "Error generating mip maps", "D3D9Texture::_blitImageToCubeTex" );
01166             }
01167             mpCubeTex->GenerateMipSubLevels();
01168 
01169         }
01170 
01171         SAFE_RELEASE(mpTmpCubeTex);
01172 
01173     }
01174     /****************************************************************************************/
01175     D3DFORMAT D3D9Texture::_chooseD3DFormat()
01176     {
01177         // choose wise wich D3D format we'll use ;)
01178         if( mFinalBpp > 16 && mHasAlpha )
01179             return D3DFMT_A8R8G8B8;
01180         else if( mFinalBpp > 16 && !mHasAlpha )
01181             return D3DFMT_R8G8B8;
01182         else if( mFinalBpp == 16 && mHasAlpha )
01183             return D3DFMT_A4R4G4B4;
01184         else if( mFinalBpp == 16 && !mHasAlpha )
01185             return D3DFMT_R5G6B5;
01186         else
01187             Except( Exception::ERR_INVALIDPARAMS, "Unknown pixel format", "D3D9Texture::_chooseD3DFormat" );
01188     }
01189     /****************************************************************************************/
01190     void D3D9Texture::_createDepthStencil()
01191     {
01192         IDirect3DSurface9 *pSrf;
01193         D3DSURFACE_DESC srfDesc;
01194         HRESULT hr;
01195 
01196         /* Get the format of the depth stencil surface of our main render target. */
01197         hr = mpDev->GetDepthStencilSurface(&pSrf);
01198         if (FAILED(hr))
01199         {
01200             String msg = DXGetErrorDescription9(hr);
01201             Except( hr, "Error GetDepthStencilSurface : " + msg, "D3D9Texture::_createDepthStencil" );
01202             this->_freeResources();
01203         }
01204         // get it's description
01205         hr = pSrf->GetDesc(&srfDesc);
01206         if (FAILED(hr))
01207         {
01208             String msg = DXGetErrorDescription9(hr);
01209             Except( hr, "Error GetDesc : " + msg, "D3D9Texture::_createDepthStencil" );
01210             SAFE_RELEASE(pSrf);
01211             this->_freeResources();
01212         }
01213         // release the temp. surface
01214         SAFE_RELEASE(pSrf);
01218         hr = mpDev->CreateDepthStencilSurface( 
01219             mSrcWidth, 
01220             mSrcHeight, 
01221             srfDesc.Format, 
01222             srfDesc.MultiSampleType, 
01223             NULL, 
01224             FALSE, 
01225             &mpZBuff, 
01226             NULL);
01227         // cry if failed 
01228         if (FAILED(hr))
01229         {
01230             String msg = DXGetErrorDescription9(hr);
01231             Except( hr, "Error CreateDepthStencilSurface : " + msg, "D3D9Texture::_createDepthStencil" );
01232             this->_freeResources();
01233         }
01234     }
01235     /****************************************************************************************/
01236     PixelFormat D3D9Texture::_getPF(D3DFORMAT d3dPF)
01237     {
01238         switch(d3dPF)
01239         {
01240         case D3DFMT_A8:
01241             return PF_A8;
01242         case D3DFMT_A4L4:
01243             return PF_A4L4;
01244         case D3DFMT_A4R4G4B4:
01245             return PF_A4R4G4B4;
01246         case D3DFMT_A8R8G8B8:
01247             return PF_A8R8G8B8;
01248         case D3DFMT_A2R10G10B10:
01249             return PF_A2R10G10B10;
01250         case D3DFMT_L8:
01251             return PF_L8;
01252         case D3DFMT_X1R5G5B5:
01253         case D3DFMT_R5G6B5:
01254             return PF_R5G6B5;
01255         case D3DFMT_X8R8G8B8:
01256         case D3DFMT_R8G8B8:
01257             return PF_R8G8B8;
01258         default:
01259             return PF_UNKNOWN;
01260         }
01261     }
01262     /****************************************************************************************/
01263     D3DFORMAT D3D9Texture::_getPF(PixelFormat ogrePF)
01264     {
01265         switch(ogrePF)
01266         {
01267         case PF_L8:
01268             return D3DFMT_L8;
01269         case PF_A8:
01270             return D3DFMT_A8;
01271         case PF_B5G6R5:
01272         case PF_R5G6B5:
01273             return D3DFMT_R5G6B5;
01274         case PF_B4G4R4A4:
01275         case PF_A4R4G4B4:
01276             return D3DFMT_A4R4G4B4;
01277         case PF_B8G8R8:
01278         case PF_R8G8B8:
01279             return D3DFMT_R8G8B8;
01280         case PF_B8G8R8A8:
01281         case PF_A8R8G8B8:
01282             return D3DFMT_A8R8G8B8;
01283         case PF_L4A4:
01284         case PF_A4L4:
01285             return D3DFMT_A4L4;
01286         case PF_B10G10R10A2:
01287         case PF_A2R10G10B10:
01288             return D3DFMT_A2R10G10B10;
01289         case PF_UNKNOWN:
01290         default:
01291             return D3DFMT_UNKNOWN;
01292         }
01293     }
01294     /****************************************************************************************/
01295 }

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:09 2004