//! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture void CD3D8Texture::regenerateMipMapLevels(void* mipmapData) { if (mipmapData) { core::dimension2du size = TextureSize; u32 level=0; do { if (size.Width>1) size.Width /=2; if (size.Height>1) size.Height /=2; ++level; IDirect3DSurface8* mipSurface = 0; HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); if (FAILED(hr) || !mipSurface) { os::Printer::log("Could not get mipmap level", ELL_WARNING); return; } D3DSURFACE_DESC mipDesc; mipSurface->GetDesc(&mipDesc); D3DLOCKED_RECT miplr; // lock mipmap surface if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) { mipSurface->Release(); os::Printer::log("Could not lock texture", ELL_WARNING); return; } memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; // unlock mipSurface->UnlockRect(); // release mipSurface->Release(); } while (size.Width != 1 || size.Height != 1); } else if (HasMipMaps) { // create mip maps. #ifndef _IRR_USE_D3DXFilterTexture_ // The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when // compiling with both D3D 8 and 9. HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT , D3DX_DEFAULT ); if (FAILED(hr)) #endif createMipMaps(); } }
//! constructor CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, u32 flags, const char* name) : ITexture(name), Image(image), Texture(0), RTTSurface(0), Driver(driver), TextureSize(0,0), ImageSize(0,0), Pitch(0), HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) { #ifdef _DEBUG setDebugName("CD3D9Texture"); #endif const bool generateMipLevels = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Device=driver->getExposedVideoData().D3D9.D3DDev9; if (Device) Device->AddRef(); if (Image) { Image->grab(); if (createTexture(flags)) { if (copyTexture() && generateMipLevels) { // create mip maps. #ifdef _IRR_USE_D3DXFilterTexture_ // The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT); if (FAILED(hr)) os::Printer::log("Could not create direct3d mip map levels.", ELL_WARNING); else HasMipMaps = true; #else createMipMaps(); HasMipMaps = true; #endif } } else os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING); } }
// The D3DXFilterTexture function seems to get linked wrong when // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when // compiling with both D3D 8 and 9. bool CD3D8Texture::createMipMaps(u32 level) { if (level==0) return true; IDirect3DSurface8* upperSurface = 0; IDirect3DSurface8* lowerSurface = 0; // get upper level HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface); if (FAILED(hr) || !upperSurface) { os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING); return false; } // get lower level hr = Texture->GetSurfaceLevel(level, &lowerSurface); if (FAILED(hr) || !lowerSurface) { os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING); upperSurface->Release(); return false; } D3DSURFACE_DESC upperDesc, lowerDesc; upperSurface->GetDesc(&upperDesc); lowerSurface->GetDesc(&lowerDesc); D3DLOCKED_RECT upperlr; D3DLOCKED_RECT lowerlr; // lock upper surface if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0))) { os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING); upperSurface->Release(); lowerSurface->Release(); return false; } // lock lower surface if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0))) { os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING); upperSurface->UnlockRect(); upperSurface->Release(); lowerSurface->Release(); return false; } if (upperDesc.Format != lowerDesc.Format) { os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING); } else { if (upperDesc.Format == D3DFMT_A1R5G5B5) copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else if (upperDesc.Format == D3DFMT_A8R8G8B8) copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits, lowerDesc.Width, lowerDesc.Height, upperlr.Pitch, lowerlr.Pitch); else os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING); } bool result=true; // unlock if (FAILED(upperSurface->UnlockRect())) result=false; if (FAILED(lowerSurface->UnlockRect())) result=false; // release upperSurface->Release(); lowerSurface->Release(); if (!result || upperDesc.Width < 3 || upperDesc.Height < 3) return result; // stop generating levels // generate next level return createMipMaps(level+1); }
//! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture void CD3D8Texture::regenerateMipMapLevels() { if (HasMipMaps) createMipMaps(); }