// 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 "Direct3DVolumeTexture9.hpp"

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

#include <assert.h>

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

		for(unsigned int level = 0; level < MIPMAP_LEVELS; level++)
		{
			if(level < this->levels)
			{
				volumeLevel[level] = new Direct3DVolume9(device, this, width, height, depth, format, pool, usage);
				volumeLevel[level]->bind();
			}
			else
			{
				volumeLevel[level] = 0;
			}

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

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

		for(int level = 0; level < MIPMAP_LEVELS; level++)
		{
			if(volumeLevel[level])
			{
				volumeLevel[level]->unbind();
				volumeLevel[level] = 0;
			}
		}

		resource->unlock();
	}

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

		TRACE("");

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

			return S_OK;
		}

		*object = 0;

		return NOINTERFACE(iid);
	}

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

		return Direct3DBaseTexture9::AddRef();
	}

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

		return Direct3DBaseTexture9::Release();
	}

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

		TRACE("");

		return Direct3DBaseTexture9::FreePrivateData(guid);
	}

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

		TRACE("");

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

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

		TRACE("");

		Direct3DBaseTexture9::PreLoad();
	}

	long Direct3DVolumeTexture9::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 Direct3DVolumeTexture9::GetDevice(IDirect3DDevice9 **device)
	{
		CriticalSection(this->device);

		TRACE("");

		return Direct3DBaseTexture9::GetDevice(device);
	}

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

		TRACE("");

		return Direct3DBaseTexture9::SetPriority(newPriority);
	}

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

		TRACE("");

		return Direct3DBaseTexture9::GetPriority();
	}

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

		TRACE("");

		return Direct3DBaseTexture9::GetType();
	}

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

		TRACE("");

		if(!(usage & D3DUSAGE_AUTOGENMIPMAP) || !volumeLevel[0]->hasDirtyMipmaps())
		{
			return;
		}

		resource->lock(sw::PUBLIC);

		for(unsigned int i = 0; i < levels - 1; i++)
		{
			Direct3DVolume9 *source = volumeLevel[i];
			Direct3DVolume9 *dest = volumeLevel[i + 1];

			source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
			dest->lockInternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);

			int sWidth = source->getWidth();
			int sHeight = source->getHeight();
			int sDepth = source->getDepth();

			int dWidth = dest->getWidth();
			int dHeight = dest->getHeight();
			int dDepth = dest->getDepth();

			D3DTEXTUREFILTERTYPE filter = GetAutoGenFilterType();

			float w = (float)sWidth / (float)dWidth;
			float h = (float)sHeight / (float)dHeight;
			float d = (float)sDepth / (float)dDepth;

			float z = 0.5f * d;

			for(int k = 0; k < dDepth; k++)
			{
				float y = 0.5f * h;

				for(int j = 0; j < dHeight; j++)
				{
					float x = 0.5f * w;

					for(int i = 0; i < dWidth; i++)
					{
						dest->copyInternal(source, i, j, k, x, y, z, filter > D3DTEXF_POINT);

						x += w;
					}

					y += h;
				}

				z += d;
			}

			source->unlockInternal();
			dest->unlockInternal();
		}

		volumeLevel[0]->cleanMipmaps();

		resource->unlock();
	}

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

		TRACE("");

		return Direct3DBaseTexture9::GetAutoGenFilterType();
	}

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

		TRACE("");

		return Direct3DBaseTexture9::GetLevelCount();
	}

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

		TRACE("");

		return Direct3DBaseTexture9::GetLOD();
	}

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

		TRACE("");

		return Direct3DBaseTexture9::SetAutoGenFilterType(filterType);
	}

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

		TRACE("");

		return Direct3DBaseTexture9::SetLOD(newLOD);
	}

	long Direct3DVolumeTexture9::GetVolumeLevel(unsigned int level, IDirect3DVolume9 **volume)
	{
		CriticalSection cs(device);

		TRACE("");

		*volume = 0;

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

		volumeLevel[level]->AddRef();
		*volume = volumeLevel[level];

		return D3D_OK;
	}

	long Direct3DVolumeTexture9::LockBox(unsigned int level, D3DLOCKED_BOX *lockedVolume, const D3DBOX *box, unsigned long flags)
	{
		CriticalSection cs(device);

		TRACE("");

		if(!lockedVolume || level >= GetLevelCount() || !volumeLevel[level])
		{
			return INVALIDCALL();
		}

		return volumeLevel[level]->LockBox(lockedVolume, box, flags);
	}

	long Direct3DVolumeTexture9::UnlockBox(unsigned int level)
	{
		CriticalSection cs(device);

		TRACE("");

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

		return volumeLevel[level]->UnlockBox();
	}

	long Direct3DVolumeTexture9::AddDirtyBox(const D3DBOX *dirtyBox)
	{
		CriticalSection cs(device);

		TRACE("");

	//	UNIMPLEMENTED();

		return D3D_OK;
	}

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

		TRACE("");

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

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

	Direct3DVolume9 *Direct3DVolumeTexture9::getInternalVolumeLevel(unsigned int level)
	{
		return volumeLevel[level];
	}
}
