/* D3D9Texture.cpp Written by Matthew Fisher DirectX implementation of BaseTexture. See BaseTexture.h for a definiton of the base functions. */ #ifdef USE_D3D9 D3D9Texture::D3D9Texture() { _SurfaceTopLevel = NULL; _Texture = NULL; _SurfacePlain = NULL; _Device = NULL; _Width = 0; _Height = 0; _RenderTarget = false; } D3D9Texture::~D3D9Texture() { FreeMemory(); } void D3D9Texture::FreeMemory() { ReleaseMemory(); if(_SurfacePlain != NULL) { D3DValidateRelease(_SurfacePlain); _SurfacePlain = NULL; } _RenderTarget = false; } void D3D9Texture::ReleaseMemory() { if(_Texture != NULL) { ULONG References = _Texture->Release(); //Assert(References == 0, "Non-zero reference count"); _Texture = NULL; } if(_SurfaceTopLevel != NULL) { D3DValidateRelease(_SurfaceTopLevel); _SurfaceTopLevel = NULL; } _Width = 0; _Height = 0; } void D3D9Texture::Init(GraphicsDevice &graphics) { _Device = graphics.CastD3D9().GetDevice(); } void D3D9Texture::Reset(GraphicsDevice &graphics) { _Device = graphics.CastD3D9().GetDevice(); } void D3D9Texture::UpdateMipMapLevels() { //D3DXFilterTexture(_Texture, NULL, 0, D3DX_DEFAULT); } void D3D9Texture::Allocate(D3DFORMAT Format, UINT Width, UINT Height, bool RenderTarget, UINT MipmapLevels) { if(_Width != Width || _Height != Height || _Format != Format || _RenderTarget != RenderTarget) { FreeMemory(); PersistentAssert(_Device != NULL, "D3D9Texture not associated"); DWORD Usage = 0; if(MipmapLevels != 1) { Usage |= D3DUSAGE_AUTOGENMIPMAP; } D3DPOOL Pool = D3DPOOL_MANAGED; /*if(Format == D3DFMT_DXT1) { while((Width & 3) != 0) { Width--; } while((Height & 3) != 0) { Height--; } if(Width == 0) Width = 4; if(Height == 0) Height = 4; }*/ if(RenderTarget) { Usage |= D3DUSAGE_RENDERTARGET; Pool = D3DPOOL_DEFAULT; D3DAlwaysValidate(_Device->CreateOffscreenPlainSurface(Width, Height, Format, D3DPOOL_SYSTEMMEM, &_SurfacePlain, NULL), "CreateOffscreenPlainSurface"); } D3DAlwaysValidate(_Device->CreateTexture(Width, Height, MipmapLevels, Usage, Format, Pool, &_Texture, NULL), "CreateTexture"); D3DValidate(_Texture->GetSurfaceLevel(0, &_SurfaceTopLevel), "GetSurfaceLevel"); _Width = Width; _Height = Height; _Format = Format; _RenderTarget = RenderTarget; } } void D3D9Texture::Clear() { // // requires D3DPOOL_DEFAULT // _Device->ColorFill(_SurfaceTopLevel, NULL, D3DCOLOR_ARGB(0, 0, 0, 0)); } void D3D9Texture::Load(const Bitmap &Bmp) { Allocate(D3DFMT_A8R8G8B8, Bmp.Width(), Bmp.Height(), false, 0); D3DLOCKED_RECT Rect; D3DValidate(_Texture->LockRect(0, &Rect, NULL, 0), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { RGBColor *CurRow = (RGBColor *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { RGBColor Color = Bmp[y][x]; CurRow[x] = RGBColor(Color.b, Color.g, Color.r, Color.a); } } D3DValidate(_Texture->UnlockRect(0), "UnlockRect"); UpdateMipMapLevels(); } void D3D9Texture::LoadFromFile(const String &filename, D3DFORMAT format) { FreeMemory(); D3DValidate(D3DXCreateTextureFromFileEx(_Device, filename.CString(), 0, 0, 0, 0, format, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &_Texture), "D3DXCreateTextureFromFileEx"); _Width = 1; _Height = 1; _Format = format; _RenderTarget = false; } void D3D9Texture::Load(const Grid &Data) { Allocate(D3DFMT_R32F, Data.Cols(), Data.Rows(), false, 0); D3DLOCKED_RECT Rect; D3DValidate(_Texture->LockRect(0, &Rect, NULL, 0), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { float *CurRow = (float *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { CurRow[x] = Data(y, x); } } D3DValidate(_Texture->UnlockRect(0), "UnlockRect"); } void D3D9Texture::Load(const Grid &Data) { Allocate(D3DFMT_G32R32F, Data.Cols(), Data.Rows(), false, 0); D3DLOCKED_RECT Rect; D3DValidate(_Texture->LockRect(0, &Rect, NULL, 0), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { Vec2f *CurRow = (Vec2f *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { CurRow[x] = Data(y, x); } } D3DValidate(_Texture->UnlockRect(0), "UnlockRect"); } void D3D9Texture::Load(const Grid &Data) { Allocate(D3DFMT_A32B32G32R32F, Data.Cols(), Data.Rows(), false, 0); D3DLOCKED_RECT Rect; D3DValidate(_Texture->LockRect(0, &Rect, NULL, 0), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { Vec4f *CurRow = (Vec4f *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { CurRow[x] = Vec4f(Data(y, x), 0.0f); } } D3DValidate(_Texture->UnlockRect(0), "UnlockRect"); } void D3D9Texture::Load(const Grid &Data) { Allocate(D3DFMT_A32B32G32R32F, Data.Cols(), Data.Rows(), false, 0); D3DLOCKED_RECT Rect; D3DValidate(_Texture->LockRect(0, &Rect, NULL, 0), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { Vec4f *CurRow = (Vec4f *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { CurRow[x] = Data(y, x); } } D3DValidate(_Texture->UnlockRect(0), "UnlockRect"); } void D3D9Texture::Load(D3D9Texture &Tex) { D3DAlwaysValidate(_Device->StretchRect(Tex.SurfaceTopLevel(), NULL, _SurfaceTopLevel, NULL, D3DTEXF_POINT), "StretchRect"); } void D3D9Texture::ReadData(Bitmap &Bmp) { PersistentAssert(_Width != 0 && _Height != 0 && _Format == D3DFMT_A8R8G8B8 && _RenderTarget, "ReadData called on invalid surface"); Bmp.Allocate(_Width, _Height); D3DLOCKED_RECT Rect; D3DAlwaysValidate(_Device->GetRenderTargetData(_SurfaceTopLevel, _SurfacePlain), "GetRenderTargetData"); D3DAlwaysValidate(_SurfacePlain->LockRect(&Rect, NULL, D3DLOCK_READONLY), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { RGBColor *CurRow = (RGBColor *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { Bmp[y][x] = CurRow[x]; } } D3DValidate(_SurfacePlain->UnlockRect(), "UnlockRect"); } void D3D9Texture::ReadData(Grid &Data) { PersistentAssert(_Width != 0 && _Height != 0 && _Format == D3DFMT_R32F, "ReadData called on invalid surface"); Data.Allocate(_Height, _Width); D3DLOCKED_RECT Rect; if(_RenderTarget) { D3DAlwaysValidate(_Device->GetRenderTargetData(_SurfaceTopLevel, _SurfacePlain), "GetRenderTargetData"); D3DAlwaysValidate(_SurfacePlain->LockRect(&Rect, NULL, D3DLOCK_READONLY), "LockRect"); } else { D3DAlwaysValidate(_SurfaceTopLevel->LockRect(&Rect, NULL, D3DLOCK_READONLY), "LockRect"); } BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { float *CurRow = (float *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { Data(y, x) = CurRow[x]; } } if(_RenderTarget) { D3DValidate(_SurfacePlain->UnlockRect(), "UnlockRect"); } else { D3DValidate(_SurfaceTopLevel->UnlockRect(), "UnlockRect"); } } void D3D9Texture::ReadData(Grid &Data) { PersistentAssert(_Width != 0 && _Height != 0 && _Format == D3DFMT_G32R32F && _RenderTarget, "ReadData called on invalid surface"); Data.Allocate(_Height, _Width); D3DLOCKED_RECT Rect; D3DAlwaysValidate(_Device->GetRenderTargetData(_SurfaceTopLevel, _SurfacePlain), "GetRenderTargetData"); D3DAlwaysValidate(_SurfacePlain->LockRect(&Rect, NULL, D3DLOCK_READONLY), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { Vec2f *CurRow = (Vec2f *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { Data(y, x) = CurRow[x]; } } D3DValidate(_SurfacePlain->UnlockRect(), "UnlockRect"); } void D3D9Texture::ReadData(Grid &Data) { PersistentAssert(_Width != 0 && _Height != 0 && _Format == D3DFMT_A32B32G32R32F && _RenderTarget, "ReadData called on invalid surface"); Data.Allocate(_Height, _Width); D3DLOCKED_RECT Rect; D3DAlwaysValidate(_Device->GetRenderTargetData(_SurfaceTopLevel, _SurfacePlain), "GetRenderTargetData"); D3DAlwaysValidate(_SurfacePlain->LockRect(&Rect, NULL, D3DLOCK_READONLY), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { Vec4f *CurRow = (Vec4f *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { Data(y, x) = Vec3f(CurRow[x].x, CurRow[x].y, CurRow[x].z); } } D3DValidate(_SurfacePlain->UnlockRect(), "UnlockRect"); } void D3D9Texture::ReadData(Grid &Data) { PersistentAssert(_Width != 0 && _Height != 0 && _Format == D3DFMT_A32B32G32R32F && _RenderTarget, "ReadData called on invalid surface"); Data.Allocate(_Height, _Width); D3DLOCKED_RECT Rect; D3DAlwaysValidate(_Device->GetRenderTargetData(_SurfaceTopLevel, _SurfacePlain), "GetRenderTargetData"); D3DAlwaysValidate(_SurfacePlain->LockRect(&Rect, NULL, D3DLOCK_READONLY), "LockRect"); BYTE *Bytes = (BYTE *)Rect.pBits; for(UINT y = 0; y < _Height; y++) { Vec4f *CurRow = (Vec4f *)(Bytes + y * Rect.Pitch); for(UINT x = 0; x < _Width; x++) { Data(y, x) = CurRow[x]; } } D3DValidate(_SurfacePlain->UnlockRect(), "UnlockRect"); } void D3D9Texture::Flush() { PersistentAssert(_Width != 0 && _Height != 0 && _Format == D3DFMT_A32B32G32R32F && _RenderTarget, "ReadData called on invalid surface"); D3DLOCKED_RECT Rect; D3DAlwaysValidate(_Device->GetRenderTargetData(_SurfaceTopLevel, _SurfacePlain), "GetRenderTargetData"); D3DAlwaysValidate(_SurfacePlain->LockRect(&Rect, NULL, D3DLOCK_READONLY), "LockRect"); D3DValidate(_SurfacePlain->UnlockRect(), "UnlockRect"); } void D3D9Texture::Set(int Index) { Assert(_Texture != NULL, "SetTexture called on empty texture"); _Device->SetTexture(Index, _Texture); } void D3D9Texture::SetAsRenderTarget(int Index) { Assert(_Texture != NULL && _RenderTarget, "SetAsRenderTarget on invalid texture"); D3DValidate(_Device->SetRenderTarget(Index, _SurfaceTopLevel), "SetRenderTarget"); } void D3D9Texture::SetNull(int Index) { _Device->SetTexture(Index, NULL); } #endif