// SwiftShader Software Renderer
//
// Copyright(c) 2005-2011 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//

#include "Direct3DCubeTexture9.hpp"

#include "Direct3DDevice9.hpp"
#include "Direct3DSurface9.hpp"
#include "Resource.hpp"
#include "Debug.hpp"

#include <assert.h>

namespace D3D9
{
	Direct3DCubeTexture9::Direct3DCubeTexture9(Direct3DDevice9 *device, unsigned int edgeLength, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool) : Direct3DBaseTexture9(device, D3DRTYPE_CUBETEXTURE, format, pool, levels, usage), edgeLength(edgeLength)
	{
		if(levels == 0)
		{
			this->levels = sw::log2(sw::max((int)edgeLength, 1)) + 1;
		}

		for(unsigned int face = 0; face < 6; face++)
		{
			int width = edgeLength;
			int height = edgeLength;

			for(unsigned int level = 0; level < MIPMAP_LEVELS; level++)
			{
				if(level < this->levels)
				{					
					surfaceLevel[face][level] = new Direct3DSurface9(device, this, width, height, format, pool, D3DMULTISAMPLE_NONE, 0, false, usage);
					surfaceLevel[face][level]->bind();
				}
				else
				{
					surfaceLevel[face][level] = 0;
				}

				width = sw::max(1, width / 2);
				height = sw::max(1, height / 2);
			}
		}
	}

	Direct3DCubeTexture9::~Direct3DCubeTexture9()
	{
		resource->lock(sw::DESTRUCT);

		for(unsigned int face = 0; face < 6; face++)
		{
			for(int level = 0; level < MIPMAP_LEVELS; level++)
			{
				if(surfaceLevel[face][level])
				{
					surfaceLevel[face][level]->unbind();
					surfaceLevel[face][level] = 0;
				}
			}
		}

		resource->unlock();
	}

	long Direct3DCubeTexture9::QueryInterface(const IID &iid, void **object)
	{
		CriticalSection cs(device);

		TRACE("");

		if(iid == IID_IDirect3DCubeTexture9 ||
		   iid == IID_IDirect3DBaseTexture9 ||
		   iid == IID_IDirect3DResource9 ||
		   iid == IID_IUnknown)
		{
			AddRef();
			*object = this;

			return S_OK;
		}

		*object = 0;

		return NOINTERFACE(iid);
	}

	unsigned long Direct3DCubeTexture9::AddRef()
	{
		TRACE("");

		return Direct3DBaseTexture9::AddRef();
	}

	unsigned long Direct3DCubeTexture9::Release()
	{
		TRACE("");

		return Direct3DBaseTexture9::Release();
	}

	long Direct3DCubeTexture9::FreePrivateData(const GUID &guid)
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::FreePrivateData(guid);
	}

	long Direct3DCubeTexture9::GetPrivateData(const GUID &guid, void *data, unsigned long *size)
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::GetPrivateData(guid, data, size);
	}

	void Direct3DCubeTexture9::PreLoad()
	{
		CriticalSection cs(device);

		TRACE("");

		Direct3DBaseTexture9::PreLoad();
	}

	long Direct3DCubeTexture9::SetPrivateData(const GUID &guid, const void *data, unsigned long size, unsigned long flags)
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::SetPrivateData(guid, data, size, flags);
	}

	long Direct3DCubeTexture9::GetDevice(IDirect3DDevice9 **device)
	{
		CriticalSection cs(this->device);

		TRACE("");

		return Direct3DBaseTexture9::GetDevice(device);
	}

	unsigned long Direct3DCubeTexture9::SetPriority(unsigned long newPriority)
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::SetPriority(newPriority);
	}

	unsigned long Direct3DCubeTexture9::GetPriority()
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::GetPriority();
	}

	D3DRESOURCETYPE Direct3DCubeTexture9::GetType()
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::GetType();
	}

	void Direct3DCubeTexture9::GenerateMipSubLevels()
	{
		CriticalSection cs(device);

		TRACE("");

		if(!(usage & D3DUSAGE_AUTOGENMIPMAP))
		{
			return;
		}

		resource->lock(sw::PUBLIC);

		for(unsigned int face = 0; face < 6; face++)
		{
			if(!surfaceLevel[face][0]->hasDirtyMipmaps())
			{
				continue;
			}

			for(unsigned int i = 0; i < levels - 1; i++)
			{
				device->stretchRect(surfaceLevel[face][i], 0, surfaceLevel[face][i + 1], 0, GetAutoGenFilterType());
			}

			surfaceLevel[face][0]->cleanMipmaps();
		}

		resource->unlock();
	}

	D3DTEXTUREFILTERTYPE Direct3DCubeTexture9::GetAutoGenFilterType()
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::GetAutoGenFilterType();
	}

	unsigned long Direct3DCubeTexture9::GetLevelCount()
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::GetLevelCount();
	}

	unsigned long Direct3DCubeTexture9::GetLOD()
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::GetLOD();
	}

	long Direct3DCubeTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE filterType)
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::SetAutoGenFilterType(filterType);
	}

	unsigned long Direct3DCubeTexture9::SetLOD(unsigned long newLOD)
	{
		CriticalSection cs(device);

		TRACE("");

		return Direct3DBaseTexture9::SetLOD(newLOD);
	}

	long Direct3DCubeTexture9::AddDirtyRect(D3DCUBEMAP_FACES face, const RECT *dirtyRect)
	{
		CriticalSection cs(device);

		TRACE("");

	//	UNIMPLEMENTED();

		return D3D_OK;
	}

	long Direct3DCubeTexture9::GetCubeMapSurface(D3DCUBEMAP_FACES face, unsigned int level, IDirect3DSurface9 **cubeMapSurface)
	{
		CriticalSection cs(device);

		TRACE("");

		*cubeMapSurface = 0;

		if(face >= 6 || level >= GetLevelCount() || !surfaceLevel[face][level])
		{
			return INVALIDCALL();
		}

		surfaceLevel[face][level]->AddRef();
		*cubeMapSurface = surfaceLevel[face][level];

		return D3D_OK;
	}

	long Direct3DCubeTexture9::GetLevelDesc(unsigned int level, D3DSURFACE_DESC *description)
	{
		CriticalSection cs(device);

		TRACE("");

		if(!description || level >= GetLevelCount() || !surfaceLevel[0][level])
		{
			return INVALIDCALL();
		}

		return surfaceLevel[0][level]->GetDesc(description);
	}

	long Direct3DCubeTexture9::LockRect(D3DCUBEMAP_FACES face, unsigned int level, D3DLOCKED_RECT *lockedRect, const RECT *rect, unsigned long flags)
	{
		CriticalSection cs(device);

		TRACE("");

		if(!lockedRect || face >= 6 || level >= GetLevelCount() || !surfaceLevel[face][level])
		{
			return INVALIDCALL();
		}

		return surfaceLevel[face][level]->LockRect(lockedRect, rect, flags);
	}

	long Direct3DCubeTexture9::UnlockRect(D3DCUBEMAP_FACES face, unsigned int level)
	{
		CriticalSection cs(device);

		TRACE("");

		if(face >= 6 || level >= GetLevelCount() || !surfaceLevel[face][level])
		{
			return INVALIDCALL();
		}

		return surfaceLevel[face][level]->UnlockRect();
	}

	Direct3DSurface9 *Direct3DCubeTexture9::getInternalCubeMapSurface(D3DCUBEMAP_FACES face, unsigned int level)
	{
		return surfaceLevel[face][level];
	}
}