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