#include "D3DDepthStencilBuffer.h"

D3DDepthStencilBuffer::D3DDepthStencilBuffer(uint32 width, uint32 height, uint32 sampleCount, ID3D10Device1* device)
: _depthStencil(0), _depthStencilView(0)
{
    _width = width; 
    _height = height; 
    _sampleCount = sampleCount;
    _device = device;

    createSurface(&_depthStencil, &_depthStencilView, DXGI_FORMAT_D32_FLOAT, _sampleCount, _width, _height);
}

D3DDepthStencilBuffer::~D3DDepthStencilBuffer()
{
    safeRelease(&_depthStencil);
    safeRelease(&_depthStencilView);
}

void D3DDepthStencilBuffer::resize(uint32 width, uint32 height)
{
    if ((_width != width) || (_height != height)) {
        _width = width;
        _height = height;

        createSurface(&_depthStencil, &_depthStencilView, DXGI_FORMAT_D32_FLOAT, _sampleCount, _width, _height);
    }
}

ID3D10DepthStencilView* D3DDepthStencilBuffer::getDepthStencilView()
{
    return _depthStencilView;
}

HRESULT D3DDepthStencilBuffer::createSurface(ID3D10Texture2D** ppTexture, ID3D10DepthStencilView** ppTextureDSV, DXGI_FORMAT format, uint32 sampleCount, uint32 width, uint32 height)
{
    HRESULT hr = E_FAIL;

    safeRelease(ppTexture);
    safeRelease(ppTextureDSV);

    D3D10_TEXTURE2D_DESC texDesc;
    texDesc.ArraySize = 1;
    texDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL;
    texDesc.CPUAccessFlags = 0;
    texDesc.Format = format;
    texDesc.Height = height;
    texDesc.Width = width;
    texDesc.MipLevels = 1;
    texDesc.MiscFlags = 0;
    texDesc.SampleDesc.Count = sampleCount;
    texDesc.SampleDesc.Quality = 0;
    texDesc.Usage = D3D10_USAGE_DEFAULT;

    hr = _device->CreateTexture2D(&texDesc, NULL, ppTexture);
    if (FAILED(hr)) {
        MessageBox(GetActiveWindow(), L"Unable to create texture.", L"D3DDepthStencilBuffer::createSurface()", MB_OK | MB_ICONERROR);
        return hr;
    }

    D3D10_DEPTH_STENCIL_VIEW_DESC depthViewDesc;
    depthViewDesc.Format = DXGI_FORMAT_D32_FLOAT;
    if (sampleCount > 1)
        depthViewDesc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2DMS;
    else {
        depthViewDesc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
    }
    depthViewDesc.Texture2D.MipSlice = 0;

    hr = _device->CreateDepthStencilView(*ppTexture, &depthViewDesc, ppTextureDSV);
    if (FAILED(hr)) {
        MessageBox(GetActiveWindow(), L"Unable to create depth and stencil view.", L"D3DDepthStencilBuffer::createSurface()", MB_OK | MB_ICONERROR);
        return hr;
    }

    return hr;
}
