blob: 703af92f0d269c3dec85a6162b7d6838432e220d [file] [log] [blame]
daniel@transgaming.com955377e2012-12-20 21:09:15 +00001//
2// Copyright (c) 2002-2012 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// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
8// class with derivations, classes that perform graphics API agnostic index buffer operations.
9
10#include "libGLESv2/renderer/IndexBuffer.h"
11
12#include "libGLESv2/renderer/Renderer9.h"
13
14namespace rx
15{
16
17unsigned int IndexBuffer::mCurrentSerial = 1;
18
19IndexBuffer::IndexBuffer(rx::Renderer9 *renderer, UINT size, D3DFORMAT format) : mRenderer(renderer), mBufferSize(size), mIndexBuffer(NULL)
20{
21 if (size > 0)
22 {
23 // D3D9_REPLACE
24 HRESULT result = mRenderer->createIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, &mIndexBuffer);
25 mSerial = issueSerial();
26
27 if (FAILED(result))
28 {
29 ERR("Out of memory allocating an index buffer of size %lu.", size);
30 }
31 }
32}
33
34IndexBuffer::~IndexBuffer()
35{
36 if (mIndexBuffer)
37 {
38 mIndexBuffer->Release();
39 }
40}
41
42IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const
43{
44 return mIndexBuffer;
45}
46
47unsigned int IndexBuffer::getSerial() const
48{
49 return mSerial;
50}
51
52unsigned int IndexBuffer::issueSerial()
53{
54 return mCurrentSerial++;
55}
56
57void IndexBuffer::unmap()
58{
59 if (mIndexBuffer)
60 {
61 mIndexBuffer->Unlock();
62 }
63}
64
65StreamingIndexBuffer::StreamingIndexBuffer(rx::Renderer9 *renderer, UINT initialSize, D3DFORMAT format) : IndexBuffer(renderer, initialSize, format)
66{
67 mWritePosition = 0;
68}
69
70StreamingIndexBuffer::~StreamingIndexBuffer()
71{
72}
73
74void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset)
75{
76 void *mapPtr = NULL;
77
78 if (mIndexBuffer)
79 {
80 HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
81
82 if (FAILED(result))
83 {
84 ERR(" Lock failed with error 0x%08x", result);
85 return NULL;
86 }
87
88 *offset = mWritePosition;
89 mWritePosition += requiredSpace;
90 }
91
92 return mapPtr;
93}
94
95void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
96{
97 if (requiredSpace > mBufferSize)
98 {
99 if (mIndexBuffer)
100 {
101 mIndexBuffer->Release();
102 mIndexBuffer = NULL;
103 }
104
105 mBufferSize = std::max(requiredSpace, 2 * mBufferSize);
106
107 // D3D9_REPLACE
108 HRESULT result = mRenderer->createIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, &mIndexBuffer);
109 mSerial = issueSerial();
110
111 if (FAILED(result))
112 {
113 ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
114 }
115
116 mWritePosition = 0;
117 }
118 else if (mWritePosition + requiredSpace > mBufferSize) // Recycle
119 {
120 void *dummy;
121 mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
122 mIndexBuffer->Unlock();
123
124 mWritePosition = 0;
125 }
126}
127
128StaticIndexBuffer::StaticIndexBuffer(rx::Renderer9 *renderer) : IndexBuffer(renderer, 0, D3DFMT_UNKNOWN)
129{
130 mCacheType = GL_NONE;
131}
132
133StaticIndexBuffer::~StaticIndexBuffer()
134{
135}
136
137void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset)
138{
139 void *mapPtr = NULL;
140
141 if (mIndexBuffer)
142 {
143 HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
144
145 if (FAILED(result))
146 {
147 ERR(" Lock failed with error 0x%08x", result);
148 return NULL;
149 }
150
151 *offset = 0;
152 }
153
154 return mapPtr;
155}
156
157void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
158{
159 if (!mIndexBuffer && mBufferSize == 0)
160 {
161 // D3D9_REPLACE
162 HRESULT result = mRenderer->createIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, &mIndexBuffer);
163 mSerial = issueSerial();
164
165 if (FAILED(result))
166 {
167 ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
168 }
169
170 mBufferSize = requiredSpace;
171 mCacheType = type;
172 }
173 else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
174 {
175 // Already allocated
176 }
177 else UNREACHABLE(); // Static index buffers can't be resized
178}
179
180bool StaticIndexBuffer::lookupType(GLenum type)
181{
182 return mCacheType == type;
183}
184
185UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
186{
187 IndexRange range = {offset, count};
188
189 std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
190
191 if (res == mCache.end())
192 {
193 return -1;
194 }
195
196 *minIndex = res->second.minIndex;
197 *maxIndex = res->second.maxIndex;
198 return res->second.streamOffset;
199}
200
201void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset)
202{
203 IndexRange indexRange = {offset, count};
204 IndexResult indexResult = {minIndex, maxIndex, streamOffset};
205 mCache[indexRange] = indexResult;
206}
207
208}
209