示例#1
0
MF_API void MFTexture_Unmap(MFTexture *pTexture, int element, int mipLevel)
{
	switch(pTexture->type)
	{
		case MFTexType_1D:
		case MFTexType_2D:
		{
			IDirect3DTexture9 *pTex = (IDirect3DTexture9*)pTexture->pInternalData;
			pTex->UnlockRect(mipLevel);
			break;
		}
		case MFTexType_3D:
		{
			IDirect3DVolumeTexture9 *pTex = (IDirect3DVolumeTexture9*)pTexture->pInternalData;
			pTex->UnlockBox(mipLevel);
			break;
		}
		case MFTexType_Cubemap:
		{
			IDirect3DCubeTexture9 *pTex = (IDirect3DCubeTexture9*)pTexture->pInternalData;
			pTex->UnlockRect(gD3DCubeFaces[element], mipLevel);
			break;
		}
	}
}
示例#2
0
void* DiD3D9TextureDrv::LockLevel(uint32 level, uint32 &pitch, uint32 surface)
{
    void *buffer = nullptr;
    if (mTexture)
    {
        if (mParent->GetTextureType() == TEXTURE_2D)
        {
            DI_ASSERT(surface == 0);
            IDirect3DTexture9* tex2D = static_cast<IDirect3DTexture9*>(mTexture);
            D3DLOCKED_RECT lockedRect;
            HRESULT result = tex2D->LockRect((DWORD)level, &lockedRect, 0, D3DLOCK_NOSYSLOCK);
            DX9_CHKERR(result);
            if (result == D3D_OK)
            {
                buffer = lockedRect.pBits;
                pitch = (uint32)lockedRect.Pitch;
            }
        }
        else if (mParent->GetTextureType() == TEXTURE_CUBE)
        {
            DI_ASSERT(surface >= 0 && surface <= 5);
            IDirect3DCubeTexture9* texCUBE = static_cast<IDirect3DCubeTexture9*>(mTexture);
            D3DLOCKED_RECT lockedRect;
            HRESULT result = texCUBE->LockRect((D3DCUBEMAP_FACES)surface, (DWORD)level,
                                               &lockedRect, 0, D3DLOCK_NOSYSLOCK);
            DX9_CHKERR(result);
            if (result == D3D_OK)
            {
                buffer = lockedRect.pBits;
                pitch = (uint32)lockedRect.Pitch;
            }
        }
    }
    return buffer;
}
示例#3
0
// Increments refcount on surface.
// caller must Release() the returned surface
gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface)
{
    IDirect3DBaseTexture9 *baseTexture = NULL;
    gl::Error error = getBaseTexture(&baseTexture);
    if (error.isError())
    {
        return error;
    }

    IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9*>(baseTexture);

    D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
    HRESULT result = texture->GetCubeMapSurface(face, level + mTopLevel, outSurface);

    ASSERT(SUCCEEDED(result));
    if (FAILED(result))
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
    }

    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
    if (level != 0 && isManaged() && dirty)
    {
        texture->AddDirtyRect(face, NULL);
    }

    return gl::Error(GL_NO_ERROR);
}
示例#4
0
sge::d3d9::surface::d3d_unique_ptr
sge::d3d9::texturefuncs::get_cube_map_surface(
	IDirect3DCubeTexture9 &_texture,
	sge::renderer::texture::cube_side const _side,
	sge::renderer::texture::mipmap::level const _level
)
{
	IDirect3DSurface9 *result;

	if(
		_texture.GetCubeMapSurface(
			sge::d3d9::convert::cube_side(
				_side
			),
			_level.get(),
			&result
		)
		!=
		D3D_OK
	)
		throw sge::renderer::exception(
			FCPPT_TEXT("GetCubeMapSurface failed!")
		);

	return
		sge::d3d9::surface::d3d_unique_ptr(
			result
		);
}
示例#5
0
void DiD3D9TextureDrv::UnlockLevel(uint32 level, uint32 surface)
{
    if (mTexture)
    {
        if (mParent->GetTextureType() == TEXTURE_2D)
        {
            IDirect3DTexture9* tex2D = static_cast<IDirect3DTexture9*>(mTexture);
            tex2D->UnlockRect(level);
        }
        else if (mParent->GetTextureType() == TEXTURE_CUBE)
        {
            IDirect3DCubeTexture9* texCUBE = static_cast<IDirect3DCubeTexture9*>(mTexture);
            texCUBE->UnlockRect((D3DCUBEMAP_FACES)surface, level);
        }
    }
}
示例#6
0
	void CCubeTexture::Load()
	{
		IDirect3DCubeTexture9* tex;
		if(D3DXCreateCubeTextureFromFileA(((CD3DRenderer*)g_Renderer)->GetDevice(), mUrl.Name.c_str(), &tex) != S_OK)
		{
			LogErrorAlways("Failed to load cube texture data from %s", mUrl.Name.c_str());
			throw ResourceException("Resource loading failed");
		}
		mTexture = tex;

		// Reload params
		D3DSURFACE_DESC desc;
		memset(&desc, 0, sizeof(D3DSURFACE_DESC));
		HR(tex->GetLevelDesc(0, &desc));

		mSurfaceDesc.Width = desc.Width;
		mSurfaceDesc.Height = desc.Height;
		mSurfaceDesc.Format = FromDXFormat(desc.Format);
		mSurfaceDesc.Type = SFC_CUBETEXTURE;
	}
示例#7
0
文件: DXUTMesh.cpp 项目: n-n-n/Flow2D
//-----------------------------------------------------------------------------
HRESULT CDXUTMesh::CreateMaterials( LPCWSTR strPath, IDirect3DDevice9 *pd3dDevice, D3DXMATERIAL* d3dxMtrls, DWORD dwNumMaterials )
{
    // Get material info for the mesh
    // Get the array of materials out of the buffer
    m_dwNumMaterials = dwNumMaterials;
    if( d3dxMtrls && m_dwNumMaterials > 0 )
    {
        // Allocate memory for the materials and textures
        m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
        if( m_pMaterials == NULL )
            return E_OUTOFMEMORY;
        m_pTextures = new LPDIRECT3DBASETEXTURE9[m_dwNumMaterials];
        if( m_pTextures == NULL )
            return E_OUTOFMEMORY;
        m_strMaterials = new CHAR[m_dwNumMaterials][MAX_PATH];
        if( m_strMaterials == NULL )
            return E_OUTOFMEMORY;

        // Copy each material and create its texture
        for( DWORD i=0; i<m_dwNumMaterials; i++ )
        {
            // Copy the material
            m_pMaterials[i]         = d3dxMtrls[i].MatD3D;
            m_pTextures[i]          = NULL;

            // Create a texture
            if( d3dxMtrls[i].pTextureFilename )
            {
                StringCchCopyA( m_strMaterials[i], MAX_PATH, d3dxMtrls[i].pTextureFilename );

                WCHAR strTexture[MAX_PATH];
                WCHAR strTextureTemp[MAX_PATH];
                D3DXIMAGE_INFO ImgInfo;

                // First attempt to look for texture in the same folder as the input folder.
                MultiByteToWideChar( CP_ACP, 0, d3dxMtrls[i].pTextureFilename, -1, strTextureTemp, MAX_PATH );
                strTextureTemp[MAX_PATH-1] = 0;

                StringCchCopy( strTexture, MAX_PATH, strPath );
                StringCchCat( strTexture, MAX_PATH, strTextureTemp );

                // Inspect the texture file to determine the texture type.
                if( FAILED( D3DXGetImageInfoFromFile( strTexture, &ImgInfo ) ) )
                {
                    // Search the media folder
                    if( FAILED( DXUTFindDXSDKMediaFileCch( strTexture, MAX_PATH, strTextureTemp ) ) )
                        continue;  // Can't find. Skip.

                    D3DXGetImageInfoFromFile( strTexture, &ImgInfo );
                }

                // Call the appropriate loader according to the texture type.
                switch( ImgInfo.ResourceType )
                {
                    case D3DRTYPE_TEXTURE:
                    {
                        IDirect3DTexture9 *pTex;
                        if( SUCCEEDED( D3DXCreateTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
                        {
                            // Obtain the base texture interface
                            pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
                            // Release the specialized instance
                            pTex->Release();
                        }
                        break;
                    }
                    case D3DRTYPE_CUBETEXTURE:
                    {
                        IDirect3DCubeTexture9 *pTex;
                        if( SUCCEEDED( D3DXCreateCubeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
                        {
                            // Obtain the base texture interface
                            pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
                            // Release the specialized instance
                            pTex->Release();
                        }
                        break;
                    }
                    case D3DRTYPE_VOLUMETEXTURE:
                    {
                        IDirect3DVolumeTexture9 *pTex;
                        if( SUCCEEDED( D3DXCreateVolumeTextureFromFile( pd3dDevice, strTexture, &pTex ) ) )
                        {
                            // Obtain the base texture interface
                            pTex->QueryInterface( IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i] );
                            // Release the specialized instance
                            pTex->Release();
                        }
                        break;
                    }
                }
            }
        }
    }
    return S_OK;
}
示例#8
0
bool CAXModel::Load(const char* strFileName)
{
	this->Unload();

	m_strFile = strFileName;

	LPD3DXBUFFER pAdjacencyBuffer = NULL;
	LPD3DXBUFFER pMtrlBuffer = NULL;
	if (FAILED(D3DXLoadMeshFromXA(m_strFile.c_str(), D3DXMESH_MANAGED, APROJECT_WINDOW->GetD3DDevice(), &pAdjacencyBuffer, &pMtrlBuffer, NULL, &m_dwNumMaterials, &m_pMeshObject)))
		return false;

	// Optimize the mesh for performance
	if (FAILED(m_pMeshObject->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL)))
	{
		SAFE_RELEASE(pAdjacencyBuffer);
		SAFE_RELEASE(pMtrlBuffer);
		return false;
	}

	D3DXMATERIAL* d3dxMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
	do
	{
		if (d3dxMtrls && m_dwNumMaterials > 0)
		{
			// Allocate memory for the materials and textures
			m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
			if (m_pMaterials == NULL)
				break;

			m_pTextures = new LPDIRECT3DBASETEXTURE9[m_dwNumMaterials];
			if (m_pTextures == NULL)
				break;

			m_strMaterials = new CHAR[m_dwNumMaterials][MAX_PATH];
			if (m_strMaterials == NULL)
				break;

			// Copy each material and create its texture
			for (DWORD i = 0; i < m_dwNumMaterials; i++)
			{
				// Copy the material
				m_pMaterials[i] = d3dxMtrls[i].MatD3D;
				m_pTextures[i] = NULL;

				// Create a texture
				if (d3dxMtrls[i].pTextureFilename)
				{
					strcpy_s(m_strMaterials[i], MAX_PATH, d3dxMtrls[i].pTextureFilename);

					CHAR strTexture[MAX_PATH];
					D3DXIMAGE_INFO ImgInfo;

					// First attempt to look for texture in the same folder as the input folder.
					int p = 0;
					strcpy_s(strTexture, MAX_PATH, m_strFile.c_str());
					for (DWORD j = 0; j < strlen(strTexture); j++)
					{
						if (strTexture[j] == '/')
							p = j;
					}
					strTexture[p + 1] = 0;
					strcat_s(strTexture, MAX_PATH, d3dxMtrls[i].pTextureFilename);

					// Inspect the texture file to determine the texture type.
					if (FAILED(D3DXGetImageInfoFromFileA(strTexture, &ImgInfo)))
						continue;

					// Call the appropriate loader according to the texture type.
					switch (ImgInfo.ResourceType)
					{
						case D3DRTYPE_TEXTURE:
						{
							IDirect3DTexture9* pTex;
							if (SUCCEEDED(D3DXCreateTextureFromFileA(APROJECT_WINDOW->GetD3DDevice(), strTexture, &pTex)))
							{
								pTex->QueryInterface(IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i]);
								pTex->Release();
							}
							break;
						}

						case D3DRTYPE_CUBETEXTURE:
						{
							IDirect3DCubeTexture9* pTex;
							if (SUCCEEDED(D3DXCreateCubeTextureFromFileA(APROJECT_WINDOW->GetD3DDevice(), strTexture, &pTex)))
							{
								pTex->QueryInterface(IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i]);
								pTex->Release();
							}
							break;
						}

						case D3DRTYPE_VOLUMETEXTURE:
						{
							IDirect3DVolumeTexture9* pTex;
							if (SUCCEEDED(D3DXCreateVolumeTextureFromFileA(APROJECT_WINDOW->GetD3DDevice(), strTexture, &pTex)))
							{
								pTex->QueryInterface(IID_IDirect3DBaseTexture9, (LPVOID*)&m_pTextures[i]);
								pTex->Release();
							}
							break;
						}
					}
				}
			}
		}
	} while (0);

	// Extract data from m_pMesh for easy access
	D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
	m_dwNumVertices = m_pMeshObject->GetNumVertices();
	m_dwNumFaces = m_pMeshObject->GetNumFaces();
	m_dwBytesPerVertex = m_pMeshObject->GetNumBytesPerVertex();
	m_pMeshObject->GetIndexBuffer(&m_pIB);
	m_pMeshObject->GetVertexBuffer(&m_pVB);
	m_pMeshObject->GetDeclaration(decl);
	APROJECT_WINDOW->GetD3DDevice()->CreateVertexDeclaration(decl, &m_pDecl);

	SAFE_RELEASE(pAdjacencyBuffer);
	SAFE_RELEASE(pMtrlBuffer);

	return true;
}
示例#9
0
MF_API bool MFTexture_Map(MFTexture *pTexture, int element, int mipLevel, MFLockedTexture *pLock)
{
	int numFaces = pTexture->type == MFTexType_Cubemap ? 6 : 1;
	MFDebug_Assert(element < numFaces, "Array textures not supported in D3D9!");

	int s = mipLevel*pTexture->numElements + (element ? element : 0);
	MFTextureSurface &surface = pTexture->pSurfaces[s];

	DWORD lockFlags = (pTexture->createFlags & MFTCF_TypeMask) == MFTCF_Scratch ? D3DLOCK_DISCARD : 0;

	switch(pTexture->type)
	{
		case MFTexType_1D:
		{
			IDirect3DTexture9 *pTex = (IDirect3DTexture9*)pTexture->pInternalData;

#if defined(MF_DEBUG)
			D3DSURFACE_DESC desc;
			pTex->GetLevelDesc(mipLevel, &desc);
			MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data...");
#endif

			D3DLOCKED_RECT rect;
			pTex->LockRect(mipLevel, &rect, NULL, lockFlags);

			pLock->pData = rect.pBits;
			pLock->width = surface.width;
			pLock->height = surface.height;
			pLock->depth = surface.depth;
			pLock->strideInBytes = rect.Pitch;
			pLock->sliceInBytes = rect.Pitch * surface.height;
			break;
		}
		case MFTexType_2D:
		{
			IDirect3DTexture9 *pTex = (IDirect3DTexture9*)pTexture->pInternalData;

#if defined(MF_DEBUG)
			D3DSURFACE_DESC desc;
			pTex->GetLevelDesc(mipLevel, &desc);
			MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data...");
#endif

			D3DLOCKED_RECT rect;
			pTex->LockRect(mipLevel, &rect, NULL, lockFlags);

			pLock->pData = rect.pBits;
			pLock->width = surface.width;
			pLock->height = surface.height;
			pLock->depth = surface.depth;
			pLock->strideInBytes = rect.Pitch;
			pLock->sliceInBytes = rect.Pitch * surface.height;
			break;
		}
		case MFTexType_3D:
		{
			IDirect3DVolumeTexture9 *pTex = (IDirect3DVolumeTexture9*)pTexture->pInternalData;

#if defined(MF_DEBUG)
			D3DVOLUME_DESC desc;
			pTex->GetLevelDesc(mipLevel, &desc);
			MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height && (int)desc.Depth == surface.depth, "D3D9 mip dimensions don't match the texture template data...");
#endif

			D3DLOCKED_BOX box;
			pTex->LockBox(mipLevel, &box, NULL, lockFlags);

			pLock->pData = box.pBits;
			pLock->width = surface.width;
			pLock->height = surface.height;
			pLock->depth = surface.depth;
			pLock->strideInBytes = box.RowPitch;
			pLock->sliceInBytes = box.SlicePitch;
			break;
		}
		case MFTexType_Cubemap:
		{
			IDirect3DCubeTexture9 *pTex = (IDirect3DCubeTexture9*)pTexture->pInternalData;

#if defined(MF_DEBUG)
			D3DSURFACE_DESC desc;
			pTex->GetLevelDesc(mipLevel, &desc);
			MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data...");
#endif

			D3DLOCKED_RECT rect;
			pTex->LockRect(gD3DCubeFaces[element], mipLevel, &rect, NULL, lockFlags);

			pLock->pData = rect.pBits;
			pLock->width = surface.width;
			pLock->height = surface.height;
			pLock->depth = surface.depth;
			pLock->strideInBytes = rect.Pitch;
			pLock->sliceInBytes = rect.Pitch * surface.height;
			break;
		}
	}

	return true;
}
示例#10
0
MF_API bool MFTexture_Update(MFTexture *pTexture, int element, int mipLevel, const void *pData, size_t lineStride, size_t sliceStride)
{
	int numFaces = pTexture->type == MFTexType_Cubemap ? 6 : 1;
	MFDebug_Assert(element < numFaces, "Array textures not supported in D3D9!");

	int s = mipLevel*pTexture->numElements + (element > -1 ? element : 0);
	MFTextureSurface &surface = pTexture->pSurfaces[s];

	DWORD lockFlags = (pTexture->createFlags & MFTCF_TypeMask) == MFTCF_Scratch ? D3DLOCK_DISCARD : 0;

	size_t lineBytes = (surface.bitsPerPixel * surface.width) / 8;
	if(lineStride == 0)
		lineStride = lineBytes;
	if(sliceStride == 0)
		sliceStride = lineStride * surface.width;

	switch(pTexture->type)
	{
		case MFTexType_1D:
		{
			IDirect3DTexture9 *pTex = (IDirect3DTexture9*)pTexture->pInternalData;

#if defined(MF_DEBUG)
			D3DSURFACE_DESC desc;
			pTex->GetLevelDesc(mipLevel, &desc);
			MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data...");
#endif

			D3DLOCKED_RECT rect;
			pTex->LockRect(mipLevel, &rect, NULL, lockFlags);
			MFCopyMemory(rect.pBits, pData, lineBytes);
			pTex->UnlockRect(mipLevel);
			break;
		}
		case MFTexType_2D:
		{
			IDirect3DTexture9 *pTex = (IDirect3DTexture9*)pTexture->pInternalData;

#if defined(MF_DEBUG)
			D3DSURFACE_DESC desc;
			pTex->GetLevelDesc(mipLevel, &desc);
			MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data...");
#endif

			D3DLOCKED_RECT rect;
			pTex->LockRect(mipLevel, &rect, NULL, lockFlags);

			const char *pSrc = (const char*)pData;
			char *pDest = (char*)rect.pBits;
			for(int i=0; i<surface.height; ++i)
			{
				MFCopyMemory(pDest, pSrc, lineBytes);
				pDest += rect.Pitch;
				pSrc += lineStride;
			}

			pTex->UnlockRect(mipLevel);
			break;
		}
		case MFTexType_3D:
		{
			IDirect3DVolumeTexture9 *pTex = (IDirect3DVolumeTexture9*)pTexture->pInternalData;

#if defined(MF_DEBUG)
			D3DVOLUME_DESC desc;
			pTex->GetLevelDesc(mipLevel, &desc);
			MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height && (int)desc.Depth == surface.depth, "D3D9 mip dimensions don't match the texture template data...");
#endif

			D3DLOCKED_BOX box;
			pTex->LockBox(mipLevel, &box, NULL, lockFlags);
			MFCopyMemory(box.pBits, pData, surface.bufferLength);

			const char *pSrcSlice = (const char*)pData;
			char *pDestSlice = (char*)box.pBits;
			for(int d=0; d<surface.depth; ++d)
			{
				const char *pSrcLine = pSrcSlice;
				char *pDestLine = pDestSlice;
				for(int i=0; i<surface.height; ++i)
				{
					MFCopyMemory(pDestLine, pSrcLine, lineBytes);
					pDestLine += box.RowPitch;
					pSrcLine += lineStride;
				}
				pSrcSlice += sliceStride;
				pDestSlice += box.SlicePitch;
			}

			pTex->UnlockBox(mipLevel);
			break;
		}
		case MFTexType_Cubemap:
		{
			MFDebug_Assert(element != -1, "TODO: must handle setting all surfaces at once...");

			IDirect3DCubeTexture9 *pTex = (IDirect3DCubeTexture9*)pTexture->pInternalData;

#if defined(MF_DEBUG)
			D3DSURFACE_DESC desc;
			pTex->GetLevelDesc(mipLevel, &desc);
			MFDebug_Assert((int)desc.Width == surface.width && (int)desc.Height == surface.height, "D3D9 mip dimensions don't match the texture template data...");
#endif

			D3DLOCKED_RECT rect;
			pTex->LockRect(gD3DCubeFaces[element], mipLevel, &rect, NULL, lockFlags);

			const char *pSrc = (const char*)pData;
			char *pDest = (char*)rect.pBits;
			for(int i=0; i<surface.height; ++i)
			{
				MFCopyMemory(pDest, pSrc, lineBytes);
				pDest += rect.Pitch;
				pSrc += lineStride;
			}

			pTex->UnlockRect(gD3DCubeFaces[element], mipLevel);
			break;
		}
	}

	return true;
}
示例#11
0
文件: Texture.cpp 项目: awdavies/cop
ID3DBaseTexture*	CRender::texture_load(LPCSTR fRName, u32& ret_msize)
{
    ID3DTexture2D*		pTexture2D		= NULL;
    IDirect3DCubeTexture9*	pTextureCUBE	= NULL;
    string_path				fn;
    u32						dwWidth,dwHeight;
    u32						img_size		= 0;
    int						img_loaded_lod	= 0;
    D3DFORMAT				fmt;
    u32						mip_cnt=u32(-1);
    // validation
    R_ASSERT				(fRName);
    R_ASSERT				(fRName[0]);

    // make file name
    string_path				fname;
    xr_strcpy(fname,fRName); //. andy if (strext(fname)) *strext(fname)=0;
    fix_texture_name		(fname);
    IReader* S				= NULL;
    //if (FS.exist(fn,"$game_textures$",fname,	".dds")	&& strstr(fname,"_bump"))	goto _BUMP;
    if (!FS.exist(fn,"$game_textures$",	fname,	".dds")	&& strstr(fname,"_bump"))	goto _BUMP_from_base;
    if (FS.exist(fn,"$level$",			fname,	".dds"))							goto _DDS;
    if (FS.exist(fn,"$game_saves$",		fname,	".dds"))							goto _DDS;
    if (FS.exist(fn,"$game_textures$",	fname,	".dds"))							goto _DDS;


#ifdef _EDITOR
    ELog.Msg(mtError,"Can't find texture '%s'",fname);
    return 0;
#else

    Msg("! Can't find texture '%s'",fname);
    R_ASSERT(FS.exist(fn,"$game_textures$",	"ed\\ed_not_existing_texture",".dds"));
    goto _DDS;

//	Debug.fatal(DEBUG_INFO,"Can't find texture '%s'",fname);

#endif

_DDS:
    {
        // Load and get header
        D3DXIMAGE_INFO			IMG;
        S						= FS.r_open	(fn);
#ifdef DEBUG
        Msg						("* Loaded: %s[%d]b",fn,S->length());
#endif // DEBUG
        img_size				= S->length	();
        R_ASSERT				(S);
        HRESULT const result	= D3DXGetImageInfoFromFileInMemory	(S->pointer(),S->length(),&IMG);
        if ( FAILED(result) ) {
            Msg					("! Can't get image info for texture '%s'",fn);
            FS.r_close			(S);
            string_path			temp;
            R_ASSERT			( FS.exist( temp, "$game_textures$", "ed\\ed_not_existing_texture", ".dds" ) );
            R_ASSERT			( xr_strcmp(temp,fn) );
            xr_strcpy			( fn, temp );
            goto _DDS;
        }

        if (IMG.ResourceType	== D3DRTYPE_CUBETEXTURE)			goto _DDS_CUBE;
        else														goto _DDS_2D;

_DDS_CUBE:
        {
            HRESULT const result	=
                D3DXCreateCubeTextureFromFileInMemoryEx(
                    HW.pDevice,
                    S->pointer(),S->length(),
                    D3DX_DEFAULT,
                    IMG.MipLevels,0,
                    IMG.Format,
                    D3DPOOL_MANAGED,
                    D3DX_DEFAULT,
                    D3DX_DEFAULT,
                    0,&IMG,0,
                    &pTextureCUBE
                );
            FS.r_close				(S);

            if ( FAILED(result) ) {
                Msg					("! Can't load texture '%s'",fn);
                string_path			temp;
                R_ASSERT			( FS.exist( temp, "$game_textures$", "ed\\ed_not_existing_texture", ".dds" ) );
                R_ASSERT			( xr_strcmp(temp,fn) );
                xr_strcpy			( fn, temp );
                goto _DDS;
            }

            // OK
            dwWidth					= IMG.Width;
            dwHeight				= IMG.Height;
            fmt						= IMG.Format;
            ret_msize				= calc_texture_size(img_loaded_lod, mip_cnt, img_size);
            mip_cnt					= pTextureCUBE->GetLevelCount();
            return					pTextureCUBE;
        }
_DDS_2D:
        {
            strlwr					(fn);
            // Load   SYS-MEM-surface, bound to device restrictions
            ID3DTexture2D*		T_sysmem;
            HRESULT const result	=
                D3DXCreateTextureFromFileInMemoryEx(
                    HW.pDevice,S->pointer(),S->length(),
                    D3DX_DEFAULT,D3DX_DEFAULT,
                    IMG.MipLevels,0,
                    IMG.Format,
                    D3DPOOL_SYSTEMMEM,
                    D3DX_DEFAULT,
                    D3DX_DEFAULT,
                    0,&IMG,0,
                    &T_sysmem
                );
            FS.r_close				(S);

            if ( FAILED(result) ) {
                Msg					("! Can't load texture '%s'",fn);
                string_path			temp;
                R_ASSERT			( FS.exist( temp, "$game_textures$", "ed\\ed_not_existing_texture", ".dds" ) );
                strlwr				(temp);
                R_ASSERT			( xr_strcmp(temp,fn) );
                xr_strcpy			( fn, temp );
                goto _DDS;
            }

            img_loaded_lod			= get_texture_load_lod(fn);
            pTexture2D				= TW_LoadTextureFromTexture(T_sysmem,IMG.Format, img_loaded_lod, dwWidth, dwHeight);
            mip_cnt					= pTexture2D->GetLevelCount();
            _RELEASE				(T_sysmem);

            // OK
            fmt						= IMG.Format;
            ret_msize				= calc_texture_size(img_loaded_lod, mip_cnt, img_size);
            return					pTexture2D;
        }
    }
    /*
    _BUMP:
    {
    	// Load   SYS-MEM-surface, bound to device restrictions
    	D3DXIMAGE_INFO			IMG;
    	IReader* S				= FS.r_open	(fn);
    	msize					= S->length	();
    	ID3DTexture2D*		T_height_gloss;
    	R_CHK(D3DXCreateTextureFromFileInMemoryEx(
    		HW.pDevice,	S->pointer(),S->length(),
    		D3DX_DEFAULT,D3DX_DEFAULT,	D3DX_DEFAULT,0,D3DFMT_A8R8G8B8,
    		D3DPOOL_SYSTEMMEM,			D3DX_DEFAULT,D3DX_DEFAULT,
    		0,&IMG,0,&T_height_gloss	));
    	FS.r_close				(S);
    	//TW_Save						(T_height_gloss,fname,"debug-0","original");

    	// Create HW-surface, compute normal map
    	ID3DTexture2D*	T_normal_1	= 0;
    	R_CHK(D3DXCreateTexture		(HW.pDevice,IMG.Width,IMG.Height,D3DX_DEFAULT,0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&T_normal_1));
    	R_CHK(D3DXComputeNormalMap	(T_normal_1,T_height_gloss,0,0,D3DX_CHANNEL_RED,_BUMPHEIGH));
    	//TW_Save						(T_normal_1,fname,"debug-1","normal");

    	// Transfer gloss-map
    	TW_Iterate_1OP				(T_normal_1,T_height_gloss,it_gloss_rev);
    	//TW_Save						(T_normal_1,fname,"debug-2","normal-G");

    	// Compress
    	fmt								= D3DFMT_DXT5;
    	ID3DTexture2D*	T_normal_1C	= TW_LoadTextureFromTexture(T_normal_1,fmt,psTextureLOD,dwWidth,dwHeight);
    	//TW_Save						(T_normal_1C,fname,"debug-3","normal-G-C");

    #if RENDER==R_R2
    	// Decompress (back)
    	fmt								= D3DFMT_A8R8G8B8;
    	ID3DTexture2D*	T_normal_1U	= TW_LoadTextureFromTexture(T_normal_1C,fmt,0,dwWidth,dwHeight);
    	// TW_Save						(T_normal_1U,fname,"debug-4","normal-G-CU");

    	// Calculate difference
    	ID3DTexture2D*	T_normal_1D = 0;
    	R_CHK(D3DXCreateTexture(HW.pDevice,dwWidth,dwHeight,T_normal_1U->GetLevelCount(),0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&T_normal_1D));
    	TW_Iterate_2OP				(T_normal_1D,T_normal_1,T_normal_1U,it_difference);
    	// TW_Save						(T_normal_1D,fname,"debug-5","normal-G-diff");

    	// Reverse channels back + transfer heightmap
    	TW_Iterate_1OP				(T_normal_1D,T_height_gloss,it_height_rev);
    	// TW_Save						(T_normal_1D,fname,"debug-6","normal-G-diff-H");

    	// Compress
    	fmt								= D3DFMT_DXT5;
    	ID3DTexture2D*	T_normal_2C	= TW_LoadTextureFromTexture(T_normal_1D,fmt,0,dwWidth,dwHeight);
    	// TW_Save						(T_normal_2C,fname,"debug-7","normal-G-diff-H-C");
    	_RELEASE					(T_normal_1U	);
    	_RELEASE					(T_normal_1D	);

    	//
    	string256			fnameB;
    	strconcat			(fnameB,"$user$",fname,"X");
    	ref_texture			t_temp		= dxRenderDeviceRender::Instance().Resources->_CreateTexture	(fnameB);
    	t_temp->surface_set	(T_normal_2C	);
    	_RELEASE			(T_normal_2C	);	// texture should keep reference to it by itself
    #endif

    	// release and return
    	// T_normal_1C	- normal.gloss,		reversed
    	// T_normal_2C	- 2*error.height,	non-reversed
    	_RELEASE			(T_height_gloss	);
    	_RELEASE			(T_normal_1		);
    	return				T_normal_1C;
    }
    */
_BUMP_from_base:
    {
        Msg			("! auto-generated bump map: %s",fname);
//////////////////
#ifndef _EDITOR
        if (strstr(fname,"_bump#"))
        {
            R_ASSERT2	(FS.exist(fn,"$game_textures$",	"ed\\ed_dummy_bump#",	".dds"), "ed_dummy_bump#");
            S						= FS.r_open	(fn);
            R_ASSERT2				(S, fn);
            img_size				= S->length	();
            goto		_DDS_2D;
        }
        if (strstr(fname,"_bump"))
        {
            R_ASSERT2	(FS.exist(fn,"$game_textures$",	"ed\\ed_dummy_bump",	".dds"),"ed_dummy_bump");
            S						= FS.r_open	(fn);

            R_ASSERT2	(S, fn);

            img_size				= S->length	();
            goto		_DDS_2D;
        }
#endif
//////////////////

        *strstr		(fname,"_bump")	= 0;
        R_ASSERT2	(FS.exist(fn,"$game_textures$",	fname,	".dds"),fname);

        // Load   SYS-MEM-surface, bound to device restrictions
        D3DXIMAGE_INFO			IMG;
        S						= FS.r_open	(fn);
        img_size				= S->length	();
        ID3DTexture2D*		T_base;
        R_CHK2(D3DXCreateTextureFromFileInMemoryEx(
                   HW.pDevice,	S->pointer(),S->length(),
                   D3DX_DEFAULT,D3DX_DEFAULT,	D3DX_DEFAULT,0,D3DFMT_A8R8G8B8,
                   D3DPOOL_SYSTEMMEM,			D3DX_DEFAULT,D3DX_DEFAULT,
                   0,&IMG,0,&T_base	), fn);
        FS.r_close				(S);

        // Create HW-surface
        ID3DTexture2D*	T_normal_1	= 0;
        R_CHK(D3DXCreateTexture		(HW.pDevice,IMG.Width,IMG.Height,D3DX_DEFAULT,0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM, &T_normal_1));
        R_CHK(D3DXComputeNormalMap	(T_normal_1,T_base,0,D3DX_NORMALMAP_COMPUTE_OCCLUSION,D3DX_CHANNEL_LUMINANCE,_BUMPHEIGH));

        // Transfer gloss-map
        TW_Iterate_1OP				(T_normal_1,T_base,it_gloss_rev_base);

        // Compress
        fmt								= D3DFMT_DXT5;
        img_loaded_lod					= get_texture_load_lod(fn);
        ID3DTexture2D*	T_normal_1C	= TW_LoadTextureFromTexture(T_normal_1, fmt, img_loaded_lod, dwWidth, dwHeight);
        mip_cnt							= T_normal_1C->GetLevelCount();

#if RENDER==R_R2
        // Decompress (back)
        fmt								= D3DFMT_A8R8G8B8;
        ID3DTexture2D*	T_normal_1U	= TW_LoadTextureFromTexture(T_normal_1C,fmt,0,dwWidth,dwHeight);

        // Calculate difference
        ID3DTexture2D*	T_normal_1D = 0;
        R_CHK(D3DXCreateTexture(HW.pDevice,dwWidth,dwHeight,T_normal_1U->GetLevelCount(),0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&T_normal_1D));
        TW_Iterate_2OP		(T_normal_1D,T_normal_1,T_normal_1U,it_difference);

        // Reverse channels back + transfer heightmap
        TW_Iterate_1OP		(T_normal_1D,T_base,it_height_rev_base);

        // Compress
        fmt								= D3DFMT_DXT5;
        ID3DTexture2D*	T_normal_2C	= TW_LoadTextureFromTexture(T_normal_1D,fmt,0,dwWidth,dwHeight);
        _RELEASE						(T_normal_1U	);
        _RELEASE						(T_normal_1D	);

        //
        string256			fnameB;
        strconcat			(sizeof(fnameB),fnameB,"$user$",fname,"_bumpX");
        ref_texture			t_temp			= dxRenderDeviceRender::Instance().Resources->_CreateTexture	(fnameB);
        t_temp->surface_set	(T_normal_2C	);
        _RELEASE			(T_normal_2C	);	// texture should keep reference to it by itself
#endif
        // T_normal_1C	- normal.gloss,		reversed
        // T_normal_2C	- 2*error.height,	non-reversed
        _RELEASE			(T_base);
        _RELEASE			(T_normal_1);
        ret_msize			= calc_texture_size(img_loaded_lod, mip_cnt, img_size);
        return				T_normal_1C;
    }
}