blob: 1c51b9e9856d4aa1ed49de76a624de16b2044a0c [file] [log] [blame]
//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h"
#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
namespace rx
{
IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
{
mIndexBuffer = NULL;
mBufferSize = 0;
mIndexType = 0;
mDynamic = false;
}
IndexBuffer9::~IndexBuffer9()
{
SafeRelease(mIndexBuffer);
}
gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
{
SafeRelease(mIndexBuffer);
updateSerial();
if (bufferSize > 0)
{
D3DFORMAT format = D3DFMT_UNKNOWN;
if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE)
{
format = D3DFMT_INDEX16;
}
else if (indexType == GL_UNSIGNED_INT)
{
ASSERT(mRenderer->getRendererExtensions().elementIndexUint);
format = D3DFMT_INDEX32;
}
else UNREACHABLE();
DWORD usageFlags = D3DUSAGE_WRITEONLY;
if (dynamic)
{
usageFlags |= D3DUSAGE_DYNAMIC;
}
HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
}
}
mBufferSize = bufferSize;
mIndexType = indexType;
mDynamic = dynamic;
return gl::Error(GL_NO_ERROR);
}
IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer)
{
ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer));
return static_cast<IndexBuffer9*>(indexBuffer);
}
gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
{
if (!mIndexBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
}
DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
void *mapPtr = NULL;
HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
}
*outMappedMemory = mapPtr;
return gl::Error(GL_NO_ERROR);
}
gl::Error IndexBuffer9::unmapBuffer()
{
if (!mIndexBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
}
HRESULT result = mIndexBuffer->Unlock();
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
}
return gl::Error(GL_NO_ERROR);
}
GLenum IndexBuffer9::getIndexType() const
{
return mIndexType;
}
unsigned int IndexBuffer9::getBufferSize() const
{
return mBufferSize;
}
gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
{
if (bufferSize > mBufferSize || indexType != mIndexType)
{
return initialize(bufferSize, indexType, mDynamic);
}
else
{
return gl::Error(GL_NO_ERROR);
}
}
gl::Error IndexBuffer9::discard()
{
if (!mIndexBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
}
void *dummy;
HRESULT result;
result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
}
result = mIndexBuffer->Unlock();
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
}
return gl::Error(GL_NO_ERROR);
}
D3DFORMAT IndexBuffer9::getIndexFormat() const
{
switch (mIndexType)
{
case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16;
case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16;
case GL_UNSIGNED_INT: return D3DFMT_INDEX32;
default: UNREACHABLE(); return D3DFMT_UNKNOWN;
}
}
IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const
{
return mIndexBuffer;
}
}