/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *   This file is part of
 *       _______   ______________  ______     _____
 *      / ____/ | / /  _/ ____/  |/  /   |   |__  /
 *     / __/ /  |/ // // / __/ /|_/ / /| |    /_ <
 *    / /___/ /|  // // /_/ / /  / / ___ |  ___/ /
 *   /_____/_/ |_/___/\____/_/  /_/_/  |_| /____/.
 *
 *   Copyright © 2003-2010 Brain Control, all rights reserved.
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <d3d11.h>
#include <d3dx11.h>

#include "../../eshared.hpp"

eResourceDx11::eResourceDx11()
{

}

eResourceDx11::eResourceDx11(ID3D11Device *dev, ID3D11DeviceContext *devContext, eBool dynamic) :
    m_device(dev),
    m_deviceContext(devContext),
    m_locked(eFALSE),
    m_dynamic(dynamic),
    m_resource(eNULL),
    m_shaderResourceView(eNULL),
	m_renderTargetView(eNULL),
	m_depthStencilView(eNULL)
{
    eASSERT(m_device != eNULL);
    eASSERT(m_deviceContext != eNULL);
}

eResourceDx11::~eResourceDx11()
{
    releaseResource();
}

void eResourceDx11::releaseResource()
{
    eSAFE_RELEASE_COM(m_shaderResourceView);
    eSAFE_RELEASE_COM(m_resource);
}

void eResourceDx11::createShaderResourceView()
{
	eASSERT(m_shaderResourceView == eNULL);
    HRESULT result = m_device->CreateShaderResourceView(m_resource, eNULL, &m_shaderResourceView);
    eASSERT(!FAILED(result));
}

void eResourceDx11::createRenderTargetView()
{
	eASSERT(m_renderTargetView == eNULL);
	HRESULT result = m_device->CreateRenderTargetView(m_resource, eNULL, &m_renderTargetView);
	eASSERT(!FAILED(result));
}

void eResourceDx11::createRenderTargetViewsCube()
{
	eASSERT(m_renderTargetView == eNULL);

	for(eU32 i=0;i<6;i++)
	{
		D3D11_RENDER_TARGET_VIEW_DESC desc;
		eMemSet(&desc, 0, sizeof(D3D11_RENDER_TARGET_VIEW_DESC));
		desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
		desc.Texture2DArray.FirstArraySlice = i;
		HRESULT result = m_device->CreateRenderTargetView(m_resource, &desc, &m_renderTargetViewsCube[i]);
		eASSERT(!FAILED(result));
	}
}

void eResourceDx11::createDepthStencilView()
{
	eASSERT(m_depthStencilView == eNULL);
	HRESULT result = m_device->CreateDepthStencilView(m_resource, eNULL, &m_depthStencilView);
	eASSERT(!FAILED(result));
}

ePtr eResourceDx11::lock()
{
    return lock(m_dynamic ? eLOCK_DISCARD : eLOCK_DEFAULT);
}

ePtr eResourceDx11::lock(eBufferLock locktype)
{
    eASSERT(m_locked == eFALSE);

    D3D11_MAP mapType = D3D11_MAP_WRITE_DISCARD;
    switch(locktype)
    {
    case eLOCK_DISCARD: mapType = D3D11_MAP_WRITE_DISCARD; break;
    case eLOCK_NOOVERWRITE: mapType = D3D11_MAP_WRITE_NO_OVERWRITE; break;
    }

    D3D11_MAPPED_SUBRESOURCE mappedSubResource;
    HRESULT result = m_deviceContext->Map(m_resource, 0, mapType, 0, &mappedSubResource);
    eASSERT(!FAILED(result));
    m_locked = eTRUE;

    return mappedSubResource.pData;
}

void eResourceDx11::unlock()
{
    eASSERT(m_locked != eFALSE);

    m_deviceContext->Unmap(m_resource, 0);
    m_locked = eFALSE;
}

eBool eResourceDx11::isDynamic() const
{
    return m_dynamic;
}

ID3D11ShaderResourceView * eResourceDx11::getShaderResourceView()
{
    return m_shaderResourceView;
}

ID3D11RenderTargetView * eResourceDx11::getRenderTargetView()
{
	return m_renderTargetView;
}

ID3D11RenderTargetView * eResourceDx11::getRenderTargetViewCube(eCubeMapFace face)
{
	return m_renderTargetViewsCube[face];
}

ID3D11DepthStencilView * eResourceDx11::getDepthStencilView()
{
	return m_depthStencilView;
}

ID3D11Resource * eResourceDx11::getResource()
{
	return m_resource;
}

