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

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:22 2004