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

#include <d3d11.h>

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

eIndexBufferDx11::eIndexBufferDx11()
{
}

eIndexBufferDx11::eIndexBufferDx11(const eIndexBufferDx11 &ib)
{
}

eIndexBufferDx11 & eIndexBufferDx11::operator = (eIndexBufferDx11 &ib)
{
    return *this;
}

eIndexBufferDx11::eIndexBufferDx11(ID3D11Device *dev, ID3D11DeviceContext *devContext, eU32 count, eBool dynamic) : 
    eResourceDx11(dev, devContext, dynamic),
    m_count(count)
{
    
    eASSERT(count > 0);

    upload();
}

eIndexBufferDx11::~eIndexBufferDx11()
{
    unload();
}

eBool eIndexBufferDx11::upload()
{
    eASSERT(m_resource == eNULL);

    D3D11_BUFFER_DESC desc;
    eMemSet(&desc, 0, sizeof(D3D11_BUFFER_DESC));

    desc.ByteWidth = m_count * sizeof(eU32);
    desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    desc.Usage = D3D11_USAGE_DYNAMIC;    //TODO: m_dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
	desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    HRESULT result = m_device->CreateBuffer(&desc, eNULL, (ID3D11Buffer**)&m_resource);
    eASSERT(!FAILED(result));
    return eTRUE;
}

eBool eIndexBufferDx11::unload()
{
    releaseResource();
    return eTRUE;
}

eU32 eIndexBufferDx11::getCount() const
{
    return m_count;
}

eVertexBufferDx11::eVertexBufferDx11()
{
}

eVertexBufferDx11::eVertexBufferDx11(const eVertexBufferDx11 &vb)
{
}

eVertexBufferDx11 & eVertexBufferDx11::operator = (eVertexBufferDx11 &vb)
{
    return *this;
}

eVertexBufferDx11::eVertexBufferDx11(ID3D11Device *dev, ID3D11DeviceContext *devContext, eU32 count, eU32 vertexSize, eBool dynamic) :
    eResourceDx11(dev, devContext, dynamic),
    m_vertexSize(vertexSize),
	m_count(count)
{
    eASSERT(vertexSize > 0);
	eASSERT(count > 0);

    upload();
}

eVertexBufferDx11::~eVertexBufferDx11()
{
    unload();
}

eBool eVertexBufferDx11::upload()
{
    eASSERT(m_resource == eNULL);

    D3D11_BUFFER_DESC desc;
    eMemSet(&desc, 0, sizeof(D3D11_BUFFER_DESC));

    desc.ByteWidth = m_vertexSize * m_count;
    desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    desc.Usage = D3D11_USAGE_DYNAMIC;  //TODO: m_dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
	desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    HRESULT result = m_device->CreateBuffer(&desc, eNULL, (ID3D11Buffer**)&m_resource);
    eASSERT(!FAILED(result));
    return eTRUE;
}

eBool eVertexBufferDx11::unload()
{
    releaseResource();
    return eTRUE;
}

eU32 eVertexBufferDx11::getByteSize() const
{
    return m_count * m_vertexSize;
}

eU32 eVertexBufferDx11::getVertexSize() const
{
    return m_vertexSize;
}

eConstantBufferDx11::eConstantBufferDx11()
{
}

eConstantBufferDx11::eConstantBufferDx11(const eConstantBufferDx11 &vb)
{
}

eConstantBufferDx11 & eConstantBufferDx11::operator = (eConstantBufferDx11 &vb)
{
    return *this;
}

eConstantBufferDx11::eConstantBufferDx11(ID3D11Device *dev, ID3D11DeviceContext *devContext) :
    eResourceDx11(dev, devContext, eTRUE),
    m_changed(eTRUE)
{
    eMemSet(m_constants, 0, eSHADER_CONSTANT_COUNT * sizeof(eVector4));
    upload();
}

eConstantBufferDx11::~eConstantBufferDx11()
{
    unload();
}

eBool eConstantBufferDx11::upload()
{
    eASSERT(m_resource == eNULL);

    D3D11_BUFFER_DESC desc;
    eMemSet(&desc, 0, sizeof(D3D11_BUFFER_DESC));

    desc.ByteWidth = eSHADER_CONSTANT_COUNT * sizeof(eVector4);
    desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    desc.Usage = D3D11_USAGE_DYNAMIC;
	desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    desc.StructureByteStride = sizeof(eVector4);

    HRESULT result = m_device->CreateBuffer(&desc, eNULL, (ID3D11Buffer**)&m_resource);
    eASSERT(!FAILED(result));
    return eTRUE;
}

eBool eConstantBufferDx11::unload()
{
    releaseResource();
    return eTRUE;
}

void eConstantBufferDx11::update()
{
    if (!m_changed)
        return;

    eVector4 *data = (eVector4*)lock(eLOCK_DISCARD);
    eMemCopy(data, m_constants, sizeof(eVector4) * eSHADER_CONSTANT_COUNT);
    unlock();

    m_changed = eFALSE;
}

void eConstantBufferDx11::set(eU32 offset, eF32 f)
{
    set(offset, eVector4(f));
}

void eConstantBufferDx11::set(eU32 offset, const eMatrix4x4 &m)
{
    set(offset,   eVector4(m.m11, m.m12, m.m13, m.m14));
    set(offset+1, eVector4(m.m21, m.m22, m.m23, m.m24));
    set(offset+2, eVector4(m.m31, m.m32, m.m33, m.m34));
    set(offset+3, eVector4(m.m41, m.m42, m.m43, m.m44));
}

void eConstantBufferDx11::set(eU32 offset, const eColor &v)
{
    eASSERT(offset < eSHADER_CONSTANT_COUNT);
    m_constants[offset] = eVector4(v.redF(), v.greenF(), v.blueF(), v.alphaF());
    m_changed = eTRUE;
}

void eConstantBufferDx11::set(eU32 offset, const eVector4 &v)
{
    eASSERT(offset < eSHADER_CONSTANT_COUNT);
    m_constants[offset] = v;
    m_changed = eTRUE;
}

void eConstantBufferDx11::set(eU32 offset, const eVector3 &v)
{
    set(offset, eVector4(v.x, v.y, v.z, 0.0f));
}

void eConstantBufferDx11::set(eU32 offset, const eVector2 &v)
{
    set(offset, eVector4(v.x, v.y, 0.0f, 0.0f));
}

