/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2005 The OGRE Team Also see acknowledgements in Readme.html This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. ----------------------------------------------------------------------------- */ #include "OgreD3D7Texture.h" #include "OgreException.h" #include "OgreImage.h" #include "OgreLogManager.h" #include "OgreHardwarePixelBuffer.h" #include "OgreRoot.h" namespace Ogre { D3DX_SURFACEFORMAT D3DTexture::OgreFormat_to_D3DXFormat( PixelFormat format ) { switch( format ) { case PF_R8G8B8: return D3DX_SF_R8G8B8; case PF_A8R8G8B8: return D3DX_SF_A8R8G8B8; case PF_X8R8G8B8: return D3DX_SF_X8R8G8B8; case PF_R5G6B5: return D3DX_SF_R5G6B5; case PF_A4R4G4B4: return D3DX_SF_A4R4G4B4; case PF_L8: return D3DX_SF_L8; case PF_BYTE_LA: // Assume little endian return D3DX_SF_A8L8; case PF_DXT1: return D3DX_SF_DXT1; case PF_DXT3: return D3DX_SF_DXT3; case PF_DXT5: return D3DX_SF_DXT5; case PF_A8: return D3DX_SF_A8; default: return D3DX_SF_UNKNOWN; } } PixelFormat D3DTexture::closestD3DXFormat( PixelFormat format ) { if(OgreFormat_to_D3DXFormat(format) != D3DX_SF_UNKNOWN) { // Format is directly supported -- great! return format; } switch(format) { case PF_B5G6R5: return PF_R5G6B5; case PF_B8G8R8: return PF_R8G8B8; case PF_B8G8R8A8: return PF_A8R8G8B8; default: return PF_A8R8G8B8; } } bool D3DTexture::OgreFormat_to_DDPixelFormat( PixelFormat format, DDPIXELFORMAT & out ) { D3DX_SURFACEFORMAT fmt = OgreFormat_to_D3DXFormat(format); if(fmt != D3DX_SF_UNKNOWN) { D3DXMakeDDPixelFormat(fmt, &out); return true; } return false; #if 0 memset( &out, 0, sizeof( DDPIXELFORMAT ) ); out.dwSize = sizeof( DDPIXELFORMAT ); if(PixelUtil::isNativeEndian(format)) { int depths[4]; uint32 masks[4]; size_t elemBits = PixelUtil::getNumElemBits(format); PixelUtil::getBitDepths(format, depths); PixelUtil::getBitMasks(format, masks); if(PixelUtil::isLuminance(format)) { out.dwFlags = DDPF_LUMINANCE; out.dwLuminanceBitCount = elemBits; out.dwLuminanceBitMask = masks[0]; if(PixelUtil::hasAlpha(format)) { out.dwFlags |= DDPF_ALPHAPIXELS; out.dwLuminanceAlphaBitMask = masks[3]; } } else if(depths[0]==0 && depths[1]==0 && depths[2] == 0 && depths[3] != 0) { // Alpha only format out.dwFlags = DDPF_ALPHA; out.dwAlphaBitDepth = elemBits; } else { // RGB[A] format out.dwFlags = DDPF_RGB; out.dwRGBBitCount = elemBits; out.dwRBitMask = masks[0]; out.dwGBitMask = masks[1]; out.dwBBitMask = masks[2]; if(PixelUtil::hasAlpha(format)) { out.dwFlags |= DDPF_ALPHAPIXELS; out.dwRGBAlphaBitMask = masks[3]; } } } else { switch( format ) { case PF_BYTE_LA: // Assume little endian out.dwFlags = DDPF_LUMINANCE | DDPF_ALPHAPIXELS; out.dwLuminanceBitCount = 16; out.dwLuminanceAlphaBitMask = 0xff00; out.dwLuminanceBitMask = 0x00ff; break; default: // Error unknown format return false; } } return true; #endif } //--------------------------------------------------------------------------------------------- D3DTexture::D3DTexture(ResourceManager* creator, const String& name, ResourceHandle handle, const String& group, bool isManual, ManualResourceLoader* loader, IDirect3DDevice7 * lpDirect3dDevice) :Texture(creator, name, handle, group, isManual, loader), mD3DDevice(lpDirect3dDevice), mRestoring(false) { mD3DDevice->AddRef(); } //--------------------------------------------------------------------------------------------- D3DTexture::~D3DTexture() { __safeRelease( &mD3DDevice ); // have to call this here reather than in Resource destructor // since calling virtual methods in base destructors causes crash if (mIsLoaded) { unload(); } else { freeInternalResources(); } } //--------------------------------------------------------------------------------------------- void D3DTexture::loadImage( const Image & img ) { // Use OGRE its own codecs std::vector imagePtrs; imagePtrs.push_back(&img); _loadImages( imagePtrs ); } //--------------------------------------------------------------------------------------------- void D3DTexture::loadImage3D( const Image imgs[] ) { // Use OGRE its own codecs std::vector imagePtrs; imagePtrs.push_back(&imgs[0]); imagePtrs.push_back(&imgs[1]); imagePtrs.push_back(&imgs[2]); imagePtrs.push_back(&imgs[3]); imagePtrs.push_back(&imgs[4]); imagePtrs.push_back(&imgs[5]); _loadImages( imagePtrs ); } //--------------------------------------------------------------------------------------------- void D3DTexture::createInternalResourcesImpl(void) { // Skip this if we're restoring device // We're using the generic load() but skipping init since DD can restore that if (!mRestoring) { if (mTextureType == TEX_TYPE_CUBE_MAP) { createSurface3D(); } else if(mTextureType == TEX_TYPE_2D) { createSurface2D(); } else { OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Unknown texture type", "D3DTexture::createInternalResources" ); } _createSurfaceList(); } } //--------------------------------------------------------------------------------------------- void D3DTexture::restoreFromLostDevice(void) { if (mIsLoaded && !(mUsage & TU_RENDERTARGET)) { mRestoring = true; // Mark as unloaded even though we're not so we can reload content mIsLoaded = false; load(); mRestoring = false; } } //--------------------------------------------------------------------------------------------- void D3DTexture::loadImpl(void) { if (mTextureType == TEX_TYPE_CUBE_MAP) { _constructCubeFaceNames(mName); Image imgs[6]; for (int face = 0; face < 6; ++face) { imgs[face].load(mCubeFaceNames[face], mGroup); } loadImage3D(imgs); } else if(mTextureType == TEX_TYPE_2D) { Image img; img.load(mName, mGroup); loadImage( img ); } else { OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Unknown texture type", "D3DTexture::loadImpl" ); } } //--------------------------------------------------------------------------------------------- void D3DTexture::copyToTexture(TexturePtr& target ) { HRESULT hr; if( FAILED( hr = ((D3DTexture*)(target.get()))->getDDSurface()->Blt( NULL, mSurface, NULL, DDBLT_WAIT, NULL ) ) ) { if(hr != DDERR_SURFACELOST) OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR, "Couldn't blit!", "D3DTexture::copyToTexture" ); } } //--------------------------------------------------------------------------------------------- void D3DTexture::freeInternalResourcesImpl() { __safeRelease( &mSurface ); } //--------------------------------------------------------------------------------------------- void D3DTexture::_chooseD3DFormat(DDPIXELFORMAT &ddpf) { //mFormat = closestD3DXFormat(mFormat); //OgreFormat_to_DDPixelFormat(mFormat, ddpf); /* The pixel format is always RGB */ ddpf.dwFlags = DDPF_RGB; ddpf.dwRGBBitCount = mFinalBpp; if( mHasAlpha ) { ddpf.dwFlags |= DDPF_ALPHAPIXELS; } /* Compute the bit masks */ if( mFinalBpp == 16 ) { if( mHasAlpha ) { /* 4-4-4-4 ARGB */ ddpf.dwRGBAlphaBitMask = 0xf000; ddpf.dwRBitMask = 0x0f00; ddpf.dwGBitMask = 0x00f0; ddpf.dwBBitMask = 0x000f; mFormat = PF_A4R4G4B4; } else { /* 5-6-5 RGB */ ddpf.dwRBitMask = 0xf800; ddpf.dwGBitMask = 0x07e0; ddpf.dwBBitMask = 0x001f; mFormat = PF_R5G6B5; } } else { if( mHasAlpha ) { /* 8-8-8-8 ARGB */ ddpf.dwRGBAlphaBitMask = 0xff000000; ddpf.dwRBitMask = 0x00ff0000; ddpf.dwGBitMask = 0x0000ff00; ddpf.dwBBitMask = 0x000000ff; mFormat = PF_A8R8G8B8; } else { /* 8-8-8 RGB */ ddpf.dwRBitMask = 0xff0000; ddpf.dwGBitMask = 0x00ff00; ddpf.dwBBitMask = 0x0000ff; mFormat = PF_X8R8G8B8; } } } //--------------------------------------------------------------------------------------------- void D3DTexture::createSurface2D(void) { D3DDEVICEDESC7 ddDesc; ZeroMemory( &ddDesc, sizeof(D3DDEVICEDESC7) ); if( FAILED( mD3DDevice->GetCaps( &ddDesc ) ) ) OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR, "Could not retrieve Direct3D Device caps.", "D3DTexture::createSurfaces" ); // Create a surface descriptor. DDSURFACEDESC2 ddsd; D3DUtil_InitSurfaceDesc( ddsd ); ddsd.dwSize = sizeof(DDSURFACEDESC2); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; ddsd.ddsCaps.dwCaps2 = 0; ddsd.dwWidth = mSrcWidth; ddsd.dwHeight = mSrcHeight; /* If the texture is a render target, set the corresponding flags */ if( mUsage & TU_RENDERTARGET ) { ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY; ddsd.ddsCaps.dwCaps2 = 0; mNumRequestedMipmaps = 0; } else { ddsd.ddsCaps.dwCaps2 = DDSCAPS2_D3DTEXTUREMANAGE; } /* If we want to have mip-maps, set the flags. Note that if the texture is the render target type mip-maps are automatically disabled. */ if( mNumRequestedMipmaps ) { ddsd.dwFlags |= DDSD_MIPMAPCOUNT; ddsd.dwMipMapCount = mNumRequestedMipmaps; ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX; } _chooseD3DFormat(ddsd.ddpfPixelFormat); /* Change texture size so that it is a power of 2, if needed. */ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 ) { for( ddsd.dwWidth = 1; mSrcWidth > ddsd.dwWidth; ddsd.dwWidth <<= 1 ); for( ddsd.dwHeight = 1; mSrcHeight > ddsd.dwHeight; ddsd.dwHeight <<= 1 ); } /* Change texture size so that it is square, if needed. Note that we made it a power of 2 in the above test, so here we just have to find the bigger dimension and make it the side length. */ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) { if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth; else ddsd.dwWidth = ddsd.dwHeight; } /* Register the possibly modified dimensions. */ mWidth = ddsd.dwWidth; mHeight = ddsd.dwHeight; mIsLoaded = true; LPDIRECTDRAWSURFACE7 pddsRender; LPDIRECTDRAW7 pDD; /* Get a DirectDraw interface. */ mD3DDevice->GetRenderTarget( &pddsRender ); pddsRender->GetDDInterface( (VOID**)&pDD ); pddsRender->Release(); if( mUsage & TU_RENDERTARGET ) { /* Get the pixel format of the primary surface - we need it because render target surfaces need to have the same pixel format. */ IDirectDrawSurface7 * pddsPrimarySurface; pDD->GetGDISurface( &pddsPrimarySurface ); pddsPrimarySurface->GetPixelFormat( &( ddsd.ddpfPixelFormat ) ); pddsPrimarySurface->Release(); } HRESULT hr; /* Now create the surface. */ if( FAILED( hr = pDD->CreateSurface( &ddsd, &mSurface, NULL ) ) ) { pDD->Release(); OGRE_EXCEPT( hr, "Could not create DirectDraw surface.", "D3DTexture::createSurfaces" ); } if( mUsage & TU_RENDERTARGET ) { LPDIRECTDRAWSURFACE7 pddsZBuffer, pddsBackBuffer, pddsTexZBuffer; DDSCAPS2 ZBuffDDSCaps; DDSURFACEDESC2 ZBuffDDSD; ZBuffDDSCaps.dwCaps = DDSCAPS_ZBUFFER; ZBuffDDSCaps.dwCaps2 = ZBuffDDSCaps.dwCaps3 = ZBuffDDSCaps.dwCaps4 = 0; memset( &ZBuffDDSD, 0, sizeof( DDSURFACEDESC2 ) ); ZBuffDDSD.dwSize = sizeof( DDSURFACEDESC2 ); /* If the primary surface has an attached z-buffer, we need one for our texture too. Here, we get the primary surface's z-buffer format and we create a new Z-buffer that we attach to the our texture. */ if( SUCCEEDED( mD3DDevice->GetRenderTarget( &pddsBackBuffer ) ) ) { if( SUCCEEDED( pddsBackBuffer->GetAttachedSurface( &ZBuffDDSCaps, &pddsZBuffer ) ) ) { pddsZBuffer->GetSurfaceDesc( &ZBuffDDSD ); /* Our new Z-buffer should have the size of the new render target. */ ZBuffDDSD.dwWidth = ddsd.dwWidth; ZBuffDDSD.dwHeight = ddsd.dwHeight; hr = pDD->CreateSurface( &ZBuffDDSD, &pddsTexZBuffer, NULL ); hr = mSurface->AddAttachedSurface( pddsTexZBuffer ); pddsBackBuffer->Release(); pddsZBuffer->Release(); pddsTexZBuffer->Release(); } } } /* Release the DirectDraw interface used in the surface creation */ pDD->Release(); } //--------------------------------------------------------------------------------------------- void D3DTexture::createSurface3D(void) { D3DDEVICEDESC7 ddDesc; ZeroMemory( &ddDesc, sizeof(D3DDEVICEDESC7) ); if( FAILED( mD3DDevice->GetCaps( &ddDesc ) ) ) OGRE_EXCEPT( Exception::ERR_RENDERINGAPI_ERROR, "Could not retrieve Direct3D Device caps.", "D3DTexture::createSurfaces" ); // Create a surface descriptor. DDSURFACEDESC2 ddsd; D3DUtil_InitSurfaceDesc( ddsd ); ddsd.dwSize = sizeof(DDSURFACEDESC2); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_TEXTURE; ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP|DDSCAPS2_CUBEMAP_ALLFACES; ddsd.dwWidth = mSrcWidth; ddsd.dwHeight = mSrcHeight; /* If the texture is a render target, set the corresponding flags */ if( mUsage & TU_RENDERTARGET ) { ddsd.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY; mNumRequestedMipmaps = 0; } else { ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_D3DTEXTUREMANAGE; } /* If we want to have mip-maps, set the flags. Note that if the texture is the render target type mip-maps are automatically disabled. */ if( mNumRequestedMipmaps ) { ddsd.dwFlags |= DDSD_MIPMAPCOUNT; ddsd.dwMipMapCount = mNumRequestedMipmaps; ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP; } _chooseD3DFormat(ddsd.ddpfPixelFormat); /* Change texture size so that it is a power of 2, if needed. */ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 ) { for( ddsd.dwWidth = 1; mSrcWidth > ddsd.dwWidth; ddsd.dwWidth <<= 1 ); for( ddsd.dwHeight = 1; mSrcHeight > ddsd.dwHeight; ddsd.dwHeight <<= 1 ); } /* Change texture size so that it is square, if needed. Note that we made it a power of 2 in the above test, so here we just have to find the bigger dimension and make it the side length. */ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) { if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth; else ddsd.dwWidth = ddsd.dwHeight; } /* Register the possibly modified dimensions. */ mWidth = ddsd.dwWidth; mHeight = ddsd.dwHeight; mIsLoaded = true; LPDIRECTDRAWSURFACE7 pddsRender; LPDIRECTDRAW7 pDD; /* Get a DirectDraw interface. */ mD3DDevice->GetRenderTarget( &pddsRender ); pddsRender->GetDDInterface( (VOID**)&pDD ); pddsRender->Release(); if( mUsage & TU_RENDERTARGET ) { /* Get the pixel format of the primary surface - we need it because render target surfaces need to have the same pixel format. */ IDirectDrawSurface7 * pddsPrimarySurface; pDD->GetGDISurface( &pddsPrimarySurface ); pddsPrimarySurface->GetPixelFormat( &( ddsd.ddpfPixelFormat ) ); pddsPrimarySurface->Release(); } HRESULT hr; /* Now create the surface. */ if( FAILED( hr = pDD->CreateSurface( &ddsd, &mSurface, NULL ) ) ) { pDD->Release(); OGRE_EXCEPT( hr, "Could not create DirectDraw surface.", "D3DTexture::createSurfaces" ); } if( mUsage & TU_RENDERTARGET ) { LPDIRECTDRAWSURFACE7 pddsZBuffer, pddsBackBuffer, pddsTexZBuffer; DDSCAPS2 ZBuffDDSCaps; DDSURFACEDESC2 ZBuffDDSD; ZBuffDDSCaps.dwCaps = DDSCAPS_ZBUFFER; ZBuffDDSCaps.dwCaps2 = ZBuffDDSCaps.dwCaps3 = ZBuffDDSCaps.dwCaps4 = 0; memset( &ZBuffDDSD, 0, sizeof( DDSURFACEDESC2 ) ); ZBuffDDSD.dwSize = sizeof( DDSURFACEDESC2 ); /* If the primary surface has an attached z-buffer, we need one for our texture too. Here, we get the primary surface's z-buffer format and we create a new Z-buffer that we attach to the our texture. */ if( SUCCEEDED( mD3DDevice->GetRenderTarget( &pddsBackBuffer ) ) ) { if( SUCCEEDED( pddsBackBuffer->GetAttachedSurface( &ZBuffDDSCaps, &pddsZBuffer ) ) ) { pddsZBuffer->GetSurfaceDesc( &ZBuffDDSD ); /* Our new Z-buffer should have the size of the new render target. */ ZBuffDDSD.dwWidth = ddsd.dwWidth; ZBuffDDSD.dwHeight = ddsd.dwHeight; hr = pDD->CreateSurface( &ZBuffDDSD, &pddsTexZBuffer, NULL ); hr = mSurface->AddAttachedSurface( pddsTexZBuffer ); pddsBackBuffer->Release(); pddsZBuffer->Release(); pddsTexZBuffer->Release(); } } } /* Release the DirectDraw interface used in the surface creation */ pDD->Release(); } //--------------------------------------------------------------------------------------------- LPDIRECTDRAWSURFACE7 D3DTexture::getDDSurface(void) { return mSurface; } void D3DTexture::_constructCubeFaceNames(const String name) { // the suffixes String suffixes[6] = {"_rt", "_lf", "_up", "_dn", "_fr", "_bk"}; size_t pos = -1; String ext; // the extension String baseName; // the base name String fakeName = name; // the 'fake' name, temp. holder // first find the base name pos = fakeName.find_last_of("."); if (pos == -1) { OGRE_EXCEPT( Exception::ERR_INTERNAL_ERROR, "Invalid cube texture base name", "D3D9Texture::_constructCubeFaceNames" ); } baseName = fakeName.substr(0, pos); ext = fakeName.substr(pos); // construct the full 6 faces file names from the baseName, suffixes and extension for (size_t i = 0; i < 6; ++i) mCubeFaceNames[i] = baseName + suffixes[i] + ext; } //--------------------------------------------------------------------------------------------- HardwarePixelBufferSharedPtr D3DTexture::getBuffer(size_t face, size_t mipmap) { if(face >= getNumFaces()) OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "A three dimensional cube has six faces", "D3D9Texture::getBuffer"); if(mipmap > getNumMipmaps()) OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Mipmap index out of range", "D3D9Texture::getBuffer"); int idx = face*(mNumMipmaps+1) + mipmap; assert(idx < mSurfaceList.size()); return mSurfaceList[idx]; } //--------------------------------------------------------------------------------------------- // Macro to hide ugly cast #define GETLEVEL(face,mip) \ static_cast(mSurfaceList[face*(mNumMipmaps+1)+mip].get()) void D3DTexture::_createSurfaceList() { HRESULT hr; size_t face; mSurfaceList.clear(); // Get real number of mipmaps DDSURFACEDESC2 desc; desc.dwSize = sizeof(DDSURFACEDESC2); if(mSurface->GetSurfaceDesc(&desc) != D3D_OK) OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "Could not get surface information", "D3DTexture::_createSurfaceList()"); if(desc.dwFlags & DDSD_MIPMAPCOUNT) mNumMipmaps = desc.dwMipMapCount; else mNumMipmaps = 0; // Create the list HardwareBuffer::Usage bufusage; if ((mUsage & TU_DYNAMIC)) { bufusage = HardwareBuffer::HBU_DYNAMIC; } else { bufusage = HardwareBuffer::HBU_STATIC; } for(face=0; face < getNumFaces(); ++face) { for(size_t mip=0; mip<=mNumMipmaps; ++mip) { mSurfaceList.push_back( HardwarePixelBufferSharedPtr( new D3D7HardwarePixelBuffer(bufusage, mD3DDevice) ) ); } } // Enumerate all surfaces for (face = 0; face < getNumFaces(); ++face) { LPDIRECTDRAWSURFACE7 pCubeFace; if(mTextureType == TEX_TYPE_CUBE_MAP) { // Get cube map face to blit to DDSCAPS2 cubeCaps; ZeroMemory(&cubeCaps, sizeof(DDSCAPS2)); switch (face) { case 0: // left cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX; break; case 1: // right cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX; break; case 2: // up cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY; break; case 3: // down cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY; break; case 4: // front - NB DirectX is backwards cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ; break; case 5: // back - NB DirectX is backwards cubeCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ; break; } if (FAILED(hr = mSurface->GetAttachedSurface( &cubeCaps, &pCubeFace))) { OGRE_EXCEPT( hr, "Error getting cube face surface.", "D3DTexture::_createSurfaceList" ); } } else { pCubeFace = mSurface; pCubeFace->AddRef(); } GETLEVEL(face, 0)->bind(pCubeFace, mFormat); LPDIRECTDRAWSURFACE7 ddsMipLevel, ddsNextLevel; DDSCAPS2 ddsCaps; HRESULT mipRes = DD_OK; size_t mipLevel = 1; ZeroMemory(&ddsCaps, sizeof(DDSCAPS2)); ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; // Get the base level and increae the reference count. ddsMipLevel = pCubeFace; ddsMipLevel->AddRef(); /// While we can get a next level in the mip-map chain. while( ddsMipLevel->GetAttachedSurface( &ddsCaps, &ddsNextLevel ) == DD_OK ) { GETLEVEL(face, mipLevel)->bind(ddsNextLevel, mFormat); // Release the current level and get the next one, incrementing the mip depth. ddsMipLevel->Release(); ddsMipLevel = ddsNextLevel; mipLevel++; } // Release the last mip-map level surface. ddsMipLevel->Release(); // Release face reference pCubeFace->Release(); } // Set autogeneration of mipmaps for each face of the texture, if it is enabled if(mNumMipmaps>0 && (mUsage & TU_AUTOMIPMAP)) { for(size_t face=0; face_setMipmapping(true); } } } #undef GETLEVEL }