1//
2// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
8
9#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h"
10#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
11
12namespace rx
13{
14
15IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
16{
17    mIndexBuffer = NULL;
18    mBufferSize = 0;
19    mIndexType = 0;
20    mDynamic = false;
21}
22
23IndexBuffer9::~IndexBuffer9()
24{
25    SafeRelease(mIndexBuffer);
26}
27
28gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
29{
30    SafeRelease(mIndexBuffer);
31
32    updateSerial();
33
34    if (bufferSize > 0)
35    {
36        D3DFORMAT format = D3DFMT_UNKNOWN;
37        if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE)
38        {
39            format = D3DFMT_INDEX16;
40        }
41        else if (indexType == GL_UNSIGNED_INT)
42        {
43            ASSERT(mRenderer->getRendererExtensions().elementIndexUint);
44            format = D3DFMT_INDEX32;
45        }
46        else UNREACHABLE();
47
48        DWORD usageFlags = D3DUSAGE_WRITEONLY;
49        if (dynamic)
50        {
51            usageFlags |= D3DUSAGE_DYNAMIC;
52        }
53
54        HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
55        if (FAILED(result))
56        {
57            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
58        }
59    }
60
61    mBufferSize = bufferSize;
62    mIndexType = indexType;
63    mDynamic = dynamic;
64
65    return gl::Error(GL_NO_ERROR);
66}
67
68IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer)
69{
70    ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer));
71    return static_cast<IndexBuffer9*>(indexBuffer);
72}
73
74gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
75{
76    if (!mIndexBuffer)
77    {
78        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
79    }
80
81    DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
82
83    void *mapPtr = NULL;
84    HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
85    if (FAILED(result))
86    {
87        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
88    }
89
90    *outMappedMemory = mapPtr;
91    return gl::Error(GL_NO_ERROR);
92}
93
94gl::Error IndexBuffer9::unmapBuffer()
95{
96    if (!mIndexBuffer)
97    {
98        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
99    }
100
101    HRESULT result = mIndexBuffer->Unlock();
102    if (FAILED(result))
103    {
104        return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
105    }
106
107    return gl::Error(GL_NO_ERROR);
108}
109
110GLenum IndexBuffer9::getIndexType() const
111{
112    return mIndexType;
113}
114
115unsigned int IndexBuffer9::getBufferSize() const
116{
117    return mBufferSize;
118}
119
120gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
121{
122    if (bufferSize > mBufferSize || indexType != mIndexType)
123    {
124        return initialize(bufferSize, indexType, mDynamic);
125    }
126    else
127    {
128        return gl::Error(GL_NO_ERROR);
129    }
130}
131
132gl::Error IndexBuffer9::discard()
133{
134    if (!mIndexBuffer)
135    {
136        return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
137    }
138
139    void *dummy;
140    HRESULT result;
141
142    result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
143    if (FAILED(result))
144    {
145        return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
146    }
147
148    result = mIndexBuffer->Unlock();
149    if (FAILED(result))
150    {
151        return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
152    }
153
154    return gl::Error(GL_NO_ERROR);
155}
156
157D3DFORMAT IndexBuffer9::getIndexFormat() const
158{
159    switch (mIndexType)
160    {
161      case GL_UNSIGNED_BYTE:    return D3DFMT_INDEX16;
162      case GL_UNSIGNED_SHORT:   return D3DFMT_INDEX16;
163      case GL_UNSIGNED_INT:     return D3DFMT_INDEX32;
164      default: UNREACHABLE();   return D3DFMT_UNKNOWN;
165    }
166}
167
168IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const
169{
170    return mIndexBuffer;
171}
172
173}
174