111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com//
211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com// Use of this source code is governed by a BSD-style license that can be
411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com// found in the LICENSE file.
511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com//
611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation.
811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
9c7a4104957aa1f6fa36e4e9cf65d36b699eb05bdBrandon Jones#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h"
10c7a4104957aa1f6fa36e4e9cf65d36b699eb05bdBrandon Jones#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
1111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
1211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.comnamespace rx
1311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
1411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
1511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.comIndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
1611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
1711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    mBuffer = NULL;
1811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    mBufferSize = 0;
1911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    mDynamicUsage = false;
2011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
2111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
2211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.comIndexBuffer11::~IndexBuffer11()
2311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
24ea2286352f5eba47dfaa3e9ab418bbacfd1ba8a1Geoff Lang    SafeRelease(mBuffer);
2511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
2611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
27c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
2811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
29ea2286352f5eba47dfaa3e9ab418bbacfd1ba8a1Geoff Lang    SafeRelease(mBuffer);
3011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
3111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    updateSerial();
3211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
3311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    if (bufferSize > 0)
3411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
3511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        ID3D11Device* dxDevice = mRenderer->getDevice();
3611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
3711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        D3D11_BUFFER_DESC bufferDesc;
3811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        bufferDesc.ByteWidth = bufferSize;
3911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
4011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
4111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
4211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        bufferDesc.MiscFlags = 0;
4311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        bufferDesc.StructureByteStride = 0;
4411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
4511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
4611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        if (FAILED(result))
4711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        {
48c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
4911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        }
5011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    }
5111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
5211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    mBufferSize = bufferSize;
5311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    mIndexType = indexType;
5411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    mDynamicUsage = dynamic;
5511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
56c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    return gl::Error(GL_NO_ERROR);
5711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
5811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
5911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.comIndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer)
6011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
618b400b1e8d84c5b93dd151807504a3e4b90d1b21apatrick@chromium.org    ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer));
6211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    return static_cast<IndexBuffer11*>(indexBuffer);
6311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
6411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
65c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
6611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
67c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    if (!mBuffer)
6811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
69c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
70c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    }
7111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
72c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    // Check for integer overflows and out-out-bounds map requests
73c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    if (offset + size < offset || offset + size > mBufferSize)
74c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    {
75c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer.");
76c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    }
7711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
78c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
7911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
80c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    D3D11_MAPPED_SUBRESOURCE mappedResource;
81c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
82c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    if (FAILED(result))
8311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
84c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result);
8511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    }
86c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang
87c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
88c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    return gl::Error(GL_NO_ERROR);
8911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
9011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
91c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error IndexBuffer11::unmapBuffer()
9211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
93c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    if (!mBuffer)
9411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
95c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
9611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    }
97c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang
98c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
99c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    dxContext->Unmap(mBuffer, 0);
100c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    return gl::Error(GL_NO_ERROR);
10111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
10211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
10311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.comGLenum IndexBuffer11::getIndexType() const
10411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
10511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    return mIndexType;
10611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
10711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
10811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.comunsigned int IndexBuffer11::getBufferSize() const
10911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
11011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    return mBufferSize;
11111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
11211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
113c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
11411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
11511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    if (bufferSize > mBufferSize || indexType != mIndexType)
11611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
11711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com        return initialize(bufferSize, indexType, mDynamicUsage);
11811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    }
11911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    else
12011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
121c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_NO_ERROR);
12211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    }
12311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
12411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
125c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error IndexBuffer11::discard()
12611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
127c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    if (!mBuffer)
12811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
129c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
130c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    }
13111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
132c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
13311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
134c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    D3D11_MAPPED_SUBRESOURCE mappedResource;
135c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
136c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    if (FAILED(result))
13711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
138c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result);
13911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    }
140c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang
141c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    dxContext->Unmap(mBuffer, 0);
142c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang
143c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    return gl::Error(GL_NO_ERROR);
14411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
14511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
14611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.comDXGI_FORMAT IndexBuffer11::getIndexFormat() const
14711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
14811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    switch (mIndexType)
14911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    {
15011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com      case GL_UNSIGNED_BYTE:    return DXGI_FORMAT_R16_UINT;
15111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com      case GL_UNSIGNED_SHORT:   return DXGI_FORMAT_R16_UINT;
15211c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com      case GL_UNSIGNED_INT:     return DXGI_FORMAT_R32_UINT;
15311c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com      default: UNREACHABLE();   return DXGI_FORMAT_UNKNOWN;
15411c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    }
15511c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
15611c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
15711c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.comID3D11Buffer *IndexBuffer11::getBuffer() const
15811c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com{
15911c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com    return mBuffer;
16011c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com}
16111c2af555ad90d9079b2a55398253f165616712cdaniel@transgaming.com
162c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang}
163