1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // IndexDataManager.cpp: Defines the IndexDataManager, a class that
8*8975f5c5SAndroid Build Coastguard Worker // runs the Buffer translation process for index buffers.
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/IndexDataManager.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Buffer.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/VertexArray.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/formatutils.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/BufferD3D.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/ContextD3D.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/IndexBuffer.h"
20*8975f5c5SAndroid Build Coastguard Worker
21*8975f5c5SAndroid Build Coastguard Worker namespace rx
22*8975f5c5SAndroid Build Coastguard Worker {
23*8975f5c5SAndroid Build Coastguard Worker
24*8975f5c5SAndroid Build Coastguard Worker namespace
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker
27*8975f5c5SAndroid Build Coastguard Worker template <typename InputT, typename DestT>
ConvertIndexArray(const void * input,gl::DrawElementsType sourceType,void * output,gl::DrawElementsType destinationType,GLsizei count,bool usePrimitiveRestartFixedIndex)28*8975f5c5SAndroid Build Coastguard Worker void ConvertIndexArray(const void *input,
29*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType sourceType,
30*8975f5c5SAndroid Build Coastguard Worker void *output,
31*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType destinationType,
32*8975f5c5SAndroid Build Coastguard Worker GLsizei count,
33*8975f5c5SAndroid Build Coastguard Worker bool usePrimitiveRestartFixedIndex)
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker const InputT *in = static_cast<const InputT *>(input);
36*8975f5c5SAndroid Build Coastguard Worker DestT *out = static_cast<DestT *>(output);
37*8975f5c5SAndroid Build Coastguard Worker
38*8975f5c5SAndroid Build Coastguard Worker if (usePrimitiveRestartFixedIndex)
39*8975f5c5SAndroid Build Coastguard Worker {
40*8975f5c5SAndroid Build Coastguard Worker InputT srcRestartIndex = static_cast<InputT>(gl::GetPrimitiveRestartIndex(sourceType));
41*8975f5c5SAndroid Build Coastguard Worker DestT destRestartIndex = static_cast<DestT>(gl::GetPrimitiveRestartIndex(destinationType));
42*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker out[i] = (in[i] == srcRestartIndex ? destRestartIndex : static_cast<DestT>(in[i]));
45*8975f5c5SAndroid Build Coastguard Worker }
46*8975f5c5SAndroid Build Coastguard Worker }
47*8975f5c5SAndroid Build Coastguard Worker else
48*8975f5c5SAndroid Build Coastguard Worker {
49*8975f5c5SAndroid Build Coastguard Worker for (GLsizei i = 0; i < count; i++)
50*8975f5c5SAndroid Build Coastguard Worker {
51*8975f5c5SAndroid Build Coastguard Worker out[i] = static_cast<DestT>(in[i]);
52*8975f5c5SAndroid Build Coastguard Worker }
53*8975f5c5SAndroid Build Coastguard Worker }
54*8975f5c5SAndroid Build Coastguard Worker }
55*8975f5c5SAndroid Build Coastguard Worker
ConvertIndices(gl::DrawElementsType sourceType,gl::DrawElementsType destinationType,const void * input,GLsizei count,void * output,bool usePrimitiveRestartFixedIndex)56*8975f5c5SAndroid Build Coastguard Worker void ConvertIndices(gl::DrawElementsType sourceType,
57*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType destinationType,
58*8975f5c5SAndroid Build Coastguard Worker const void *input,
59*8975f5c5SAndroid Build Coastguard Worker GLsizei count,
60*8975f5c5SAndroid Build Coastguard Worker void *output,
61*8975f5c5SAndroid Build Coastguard Worker bool usePrimitiveRestartFixedIndex)
62*8975f5c5SAndroid Build Coastguard Worker {
63*8975f5c5SAndroid Build Coastguard Worker if (sourceType == destinationType)
64*8975f5c5SAndroid Build Coastguard Worker {
65*8975f5c5SAndroid Build Coastguard Worker const GLuint dstTypeSize = gl::GetDrawElementsTypeSize(destinationType);
66*8975f5c5SAndroid Build Coastguard Worker memcpy(output, input, count * dstTypeSize);
67*8975f5c5SAndroid Build Coastguard Worker return;
68*8975f5c5SAndroid Build Coastguard Worker }
69*8975f5c5SAndroid Build Coastguard Worker
70*8975f5c5SAndroid Build Coastguard Worker if (sourceType == gl::DrawElementsType::UnsignedByte)
71*8975f5c5SAndroid Build Coastguard Worker {
72*8975f5c5SAndroid Build Coastguard Worker ASSERT(destinationType == gl::DrawElementsType::UnsignedShort);
73*8975f5c5SAndroid Build Coastguard Worker ConvertIndexArray<GLubyte, GLushort>(input, sourceType, output, destinationType, count,
74*8975f5c5SAndroid Build Coastguard Worker usePrimitiveRestartFixedIndex);
75*8975f5c5SAndroid Build Coastguard Worker }
76*8975f5c5SAndroid Build Coastguard Worker else if (sourceType == gl::DrawElementsType::UnsignedShort)
77*8975f5c5SAndroid Build Coastguard Worker {
78*8975f5c5SAndroid Build Coastguard Worker ASSERT(destinationType == gl::DrawElementsType::UnsignedInt);
79*8975f5c5SAndroid Build Coastguard Worker ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count,
80*8975f5c5SAndroid Build Coastguard Worker usePrimitiveRestartFixedIndex);
81*8975f5c5SAndroid Build Coastguard Worker }
82*8975f5c5SAndroid Build Coastguard Worker else
83*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
84*8975f5c5SAndroid Build Coastguard Worker }
85*8975f5c5SAndroid Build Coastguard Worker
StreamInIndexBuffer(const gl::Context * context,IndexBufferInterface * buffer,const void * data,unsigned int count,gl::DrawElementsType srcType,gl::DrawElementsType dstType,bool usePrimitiveRestartFixedIndex,unsigned int * offset)86*8975f5c5SAndroid Build Coastguard Worker angle::Result StreamInIndexBuffer(const gl::Context *context,
87*8975f5c5SAndroid Build Coastguard Worker IndexBufferInterface *buffer,
88*8975f5c5SAndroid Build Coastguard Worker const void *data,
89*8975f5c5SAndroid Build Coastguard Worker unsigned int count,
90*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType srcType,
91*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType dstType,
92*8975f5c5SAndroid Build Coastguard Worker bool usePrimitiveRestartFixedIndex,
93*8975f5c5SAndroid Build Coastguard Worker unsigned int *offset)
94*8975f5c5SAndroid Build Coastguard Worker {
95*8975f5c5SAndroid Build Coastguard Worker const GLuint dstTypeBytesShift = gl::GetDrawElementsTypeShift(dstType);
96*8975f5c5SAndroid Build Coastguard Worker
97*8975f5c5SAndroid Build Coastguard Worker bool check = (count > (std::numeric_limits<unsigned int>::max() >> dstTypeBytesShift));
98*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK(GetImplAs<ContextD3D>(context), !check,
99*8975f5c5SAndroid Build Coastguard Worker "Reserving indices exceeds the maximum buffer size.", GL_OUT_OF_MEMORY);
100*8975f5c5SAndroid Build Coastguard Worker
101*8975f5c5SAndroid Build Coastguard Worker unsigned int bufferSizeRequired = count << dstTypeBytesShift;
102*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(buffer->reserveBufferSpace(context, bufferSizeRequired, dstType));
103*8975f5c5SAndroid Build Coastguard Worker
104*8975f5c5SAndroid Build Coastguard Worker void *output = nullptr;
105*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(buffer->mapBuffer(context, bufferSizeRequired, &output, offset));
106*8975f5c5SAndroid Build Coastguard Worker
107*8975f5c5SAndroid Build Coastguard Worker ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex);
108*8975f5c5SAndroid Build Coastguard Worker
109*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(buffer->unmapBuffer(context));
110*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
111*8975f5c5SAndroid Build Coastguard Worker }
112*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker // IndexDataManager implementation.
IndexDataManager(BufferFactoryD3D * factory)115*8975f5c5SAndroid Build Coastguard Worker IndexDataManager::IndexDataManager(BufferFactoryD3D *factory)
116*8975f5c5SAndroid Build Coastguard Worker : mFactory(factory), mStreamingBufferShort(), mStreamingBufferInt()
117*8975f5c5SAndroid Build Coastguard Worker {}
118*8975f5c5SAndroid Build Coastguard Worker
~IndexDataManager()119*8975f5c5SAndroid Build Coastguard Worker IndexDataManager::~IndexDataManager() {}
120*8975f5c5SAndroid Build Coastguard Worker
deinitialize()121*8975f5c5SAndroid Build Coastguard Worker void IndexDataManager::deinitialize()
122*8975f5c5SAndroid Build Coastguard Worker {
123*8975f5c5SAndroid Build Coastguard Worker mStreamingBufferShort.reset();
124*8975f5c5SAndroid Build Coastguard Worker mStreamingBufferInt.reset();
125*8975f5c5SAndroid Build Coastguard Worker }
126*8975f5c5SAndroid Build Coastguard Worker
127*8975f5c5SAndroid Build Coastguard Worker // This function translates a GL-style indices into DX-style indices, with their description
128*8975f5c5SAndroid Build Coastguard Worker // returned in translated.
129*8975f5c5SAndroid Build Coastguard Worker // GL can specify vertex data in immediate mode (pointer to CPU array of indices), which is not
130*8975f5c5SAndroid Build Coastguard Worker // possible in DX and requires streaming (Case 1). If the GL indices are specified with a buffer
131*8975f5c5SAndroid Build Coastguard Worker // (Case 2), in a format supported by DX (subcase a) then all is good.
132*8975f5c5SAndroid Build Coastguard Worker // When we have a buffer with an unsupported format (subcase b) then we need to do some translation:
133*8975f5c5SAndroid Build Coastguard Worker // we will start by falling back to streaming, and after a while will start using a static
134*8975f5c5SAndroid Build Coastguard Worker // translated copy of the index buffer.
prepareIndexData(const gl::Context * context,gl::DrawElementsType srcType,gl::DrawElementsType dstType,GLsizei count,gl::Buffer * glBuffer,const void * indices,TranslatedIndexData * translated)135*8975f5c5SAndroid Build Coastguard Worker angle::Result IndexDataManager::prepareIndexData(const gl::Context *context,
136*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType srcType,
137*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType dstType,
138*8975f5c5SAndroid Build Coastguard Worker GLsizei count,
139*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *glBuffer,
140*8975f5c5SAndroid Build Coastguard Worker const void *indices,
141*8975f5c5SAndroid Build Coastguard Worker TranslatedIndexData *translated)
142*8975f5c5SAndroid Build Coastguard Worker {
143*8975f5c5SAndroid Build Coastguard Worker GLuint srcTypeBytes = gl::GetDrawElementsTypeSize(srcType);
144*8975f5c5SAndroid Build Coastguard Worker GLuint srcTypeShift = gl::GetDrawElementsTypeShift(srcType);
145*8975f5c5SAndroid Build Coastguard Worker GLuint dstTypeShift = gl::GetDrawElementsTypeShift(dstType);
146*8975f5c5SAndroid Build Coastguard Worker
147*8975f5c5SAndroid Build Coastguard Worker BufferD3D *buffer = glBuffer ? GetImplAs<BufferD3D>(glBuffer) : nullptr;
148*8975f5c5SAndroid Build Coastguard Worker
149*8975f5c5SAndroid Build Coastguard Worker translated->indexType = dstType;
150*8975f5c5SAndroid Build Coastguard Worker translated->srcIndexData.srcBuffer = buffer;
151*8975f5c5SAndroid Build Coastguard Worker translated->srcIndexData.srcIndices = indices;
152*8975f5c5SAndroid Build Coastguard Worker translated->srcIndexData.srcIndexType = srcType;
153*8975f5c5SAndroid Build Coastguard Worker translated->srcIndexData.srcCount = count;
154*8975f5c5SAndroid Build Coastguard Worker
155*8975f5c5SAndroid Build Coastguard Worker // Context can be nullptr in perf tests.
156*8975f5c5SAndroid Build Coastguard Worker bool primitiveRestartFixedIndexEnabled =
157*8975f5c5SAndroid Build Coastguard Worker context ? context->getState().isPrimitiveRestartEnabled() : false;
158*8975f5c5SAndroid Build Coastguard Worker
159*8975f5c5SAndroid Build Coastguard Worker // Case 1: the indices are passed by pointer, which forces the streaming of index data
160*8975f5c5SAndroid Build Coastguard Worker if (glBuffer == nullptr)
161*8975f5c5SAndroid Build Coastguard Worker {
162*8975f5c5SAndroid Build Coastguard Worker translated->storage = nullptr;
163*8975f5c5SAndroid Build Coastguard Worker return streamIndexData(context, indices, count, srcType, dstType,
164*8975f5c5SAndroid Build Coastguard Worker primitiveRestartFixedIndexEnabled, translated);
165*8975f5c5SAndroid Build Coastguard Worker }
166*8975f5c5SAndroid Build Coastguard Worker
167*8975f5c5SAndroid Build Coastguard Worker // Case 2: the indices are already in a buffer
168*8975f5c5SAndroid Build Coastguard Worker unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
169*8975f5c5SAndroid Build Coastguard Worker ASSERT(srcTypeBytes * static_cast<unsigned int>(count) + offset <= buffer->getSize());
170*8975f5c5SAndroid Build Coastguard Worker
171*8975f5c5SAndroid Build Coastguard Worker bool offsetAligned = IsOffsetAligned(srcType, offset);
172*8975f5c5SAndroid Build Coastguard Worker
173*8975f5c5SAndroid Build Coastguard Worker // Case 2a: the buffer can be used directly
174*8975f5c5SAndroid Build Coastguard Worker if (offsetAligned && buffer->supportsDirectBinding() && dstType == srcType)
175*8975f5c5SAndroid Build Coastguard Worker {
176*8975f5c5SAndroid Build Coastguard Worker translated->storage = buffer;
177*8975f5c5SAndroid Build Coastguard Worker translated->indexBuffer = nullptr;
178*8975f5c5SAndroid Build Coastguard Worker translated->serial = buffer->getSerial();
179*8975f5c5SAndroid Build Coastguard Worker translated->startIndex = (offset >> srcTypeShift);
180*8975f5c5SAndroid Build Coastguard Worker translated->startOffset = offset;
181*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
182*8975f5c5SAndroid Build Coastguard Worker }
183*8975f5c5SAndroid Build Coastguard Worker
184*8975f5c5SAndroid Build Coastguard Worker translated->storage = nullptr;
185*8975f5c5SAndroid Build Coastguard Worker
186*8975f5c5SAndroid Build Coastguard Worker // Case 2b: use a static translated copy or fall back to streaming
187*8975f5c5SAndroid Build Coastguard Worker StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer();
188*8975f5c5SAndroid Build Coastguard Worker
189*8975f5c5SAndroid Build Coastguard Worker bool staticBufferInitialized = staticBuffer && staticBuffer->getBufferSize() != 0;
190*8975f5c5SAndroid Build Coastguard Worker bool staticBufferUsable =
191*8975f5c5SAndroid Build Coastguard Worker staticBuffer && offsetAligned && staticBuffer->getIndexType() == dstType;
192*8975f5c5SAndroid Build Coastguard Worker
193*8975f5c5SAndroid Build Coastguard Worker if (staticBufferInitialized && !staticBufferUsable)
194*8975f5c5SAndroid Build Coastguard Worker {
195*8975f5c5SAndroid Build Coastguard Worker buffer->invalidateStaticData(context);
196*8975f5c5SAndroid Build Coastguard Worker staticBuffer = nullptr;
197*8975f5c5SAndroid Build Coastguard Worker }
198*8975f5c5SAndroid Build Coastguard Worker
199*8975f5c5SAndroid Build Coastguard Worker if (staticBuffer == nullptr || !offsetAligned)
200*8975f5c5SAndroid Build Coastguard Worker {
201*8975f5c5SAndroid Build Coastguard Worker const uint8_t *bufferData = nullptr;
202*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(buffer->getData(context, &bufferData));
203*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferData != nullptr);
204*8975f5c5SAndroid Build Coastguard Worker
205*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(streamIndexData(context, bufferData + offset, count, srcType, dstType,
206*8975f5c5SAndroid Build Coastguard Worker primitiveRestartFixedIndexEnabled, translated));
207*8975f5c5SAndroid Build Coastguard Worker buffer->promoteStaticUsage(context, count << srcTypeShift);
208*8975f5c5SAndroid Build Coastguard Worker }
209*8975f5c5SAndroid Build Coastguard Worker else
210*8975f5c5SAndroid Build Coastguard Worker {
211*8975f5c5SAndroid Build Coastguard Worker if (!staticBufferInitialized)
212*8975f5c5SAndroid Build Coastguard Worker {
213*8975f5c5SAndroid Build Coastguard Worker const uint8_t *bufferData = nullptr;
214*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(buffer->getData(context, &bufferData));
215*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferData != nullptr);
216*8975f5c5SAndroid Build Coastguard Worker
217*8975f5c5SAndroid Build Coastguard Worker unsigned int convertCount =
218*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned int>(buffer->getSize()) >> srcTypeShift;
219*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(StreamInIndexBuffer(context, staticBuffer, bufferData, convertCount, srcType,
220*8975f5c5SAndroid Build Coastguard Worker dstType, primitiveRestartFixedIndexEnabled, nullptr));
221*8975f5c5SAndroid Build Coastguard Worker }
222*8975f5c5SAndroid Build Coastguard Worker ASSERT(offsetAligned && staticBuffer->getIndexType() == dstType);
223*8975f5c5SAndroid Build Coastguard Worker
224*8975f5c5SAndroid Build Coastguard Worker translated->indexBuffer = staticBuffer->getIndexBuffer();
225*8975f5c5SAndroid Build Coastguard Worker translated->serial = staticBuffer->getSerial();
226*8975f5c5SAndroid Build Coastguard Worker translated->startIndex = (offset >> srcTypeShift);
227*8975f5c5SAndroid Build Coastguard Worker translated->startOffset = (offset >> srcTypeShift) << dstTypeShift;
228*8975f5c5SAndroid Build Coastguard Worker }
229*8975f5c5SAndroid Build Coastguard Worker
230*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
231*8975f5c5SAndroid Build Coastguard Worker }
232*8975f5c5SAndroid Build Coastguard Worker
streamIndexData(const gl::Context * context,const void * data,unsigned int count,gl::DrawElementsType srcType,gl::DrawElementsType dstType,bool usePrimitiveRestartFixedIndex,TranslatedIndexData * translated)233*8975f5c5SAndroid Build Coastguard Worker angle::Result IndexDataManager::streamIndexData(const gl::Context *context,
234*8975f5c5SAndroid Build Coastguard Worker const void *data,
235*8975f5c5SAndroid Build Coastguard Worker unsigned int count,
236*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType srcType,
237*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType dstType,
238*8975f5c5SAndroid Build Coastguard Worker bool usePrimitiveRestartFixedIndex,
239*8975f5c5SAndroid Build Coastguard Worker TranslatedIndexData *translated)
240*8975f5c5SAndroid Build Coastguard Worker {
241*8975f5c5SAndroid Build Coastguard Worker const GLuint dstTypeShift = gl::GetDrawElementsTypeShift(dstType);
242*8975f5c5SAndroid Build Coastguard Worker
243*8975f5c5SAndroid Build Coastguard Worker IndexBufferInterface *indexBuffer = nullptr;
244*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(getStreamingIndexBuffer(context, dstType, &indexBuffer));
245*8975f5c5SAndroid Build Coastguard Worker ASSERT(indexBuffer != nullptr);
246*8975f5c5SAndroid Build Coastguard Worker
247*8975f5c5SAndroid Build Coastguard Worker unsigned int offset;
248*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(StreamInIndexBuffer(context, indexBuffer, data, count, srcType, dstType,
249*8975f5c5SAndroid Build Coastguard Worker usePrimitiveRestartFixedIndex, &offset));
250*8975f5c5SAndroid Build Coastguard Worker
251*8975f5c5SAndroid Build Coastguard Worker translated->indexBuffer = indexBuffer->getIndexBuffer();
252*8975f5c5SAndroid Build Coastguard Worker translated->serial = indexBuffer->getSerial();
253*8975f5c5SAndroid Build Coastguard Worker translated->startIndex = (offset >> dstTypeShift);
254*8975f5c5SAndroid Build Coastguard Worker translated->startOffset = offset;
255*8975f5c5SAndroid Build Coastguard Worker
256*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
257*8975f5c5SAndroid Build Coastguard Worker }
258*8975f5c5SAndroid Build Coastguard Worker
getStreamingIndexBuffer(const gl::Context * context,gl::DrawElementsType destinationIndexType,IndexBufferInterface ** outBuffer)259*8975f5c5SAndroid Build Coastguard Worker angle::Result IndexDataManager::getStreamingIndexBuffer(const gl::Context *context,
260*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType destinationIndexType,
261*8975f5c5SAndroid Build Coastguard Worker IndexBufferInterface **outBuffer)
262*8975f5c5SAndroid Build Coastguard Worker {
263*8975f5c5SAndroid Build Coastguard Worker ASSERT(outBuffer);
264*8975f5c5SAndroid Build Coastguard Worker ASSERT(destinationIndexType == gl::DrawElementsType::UnsignedShort ||
265*8975f5c5SAndroid Build Coastguard Worker destinationIndexType == gl::DrawElementsType::UnsignedInt);
266*8975f5c5SAndroid Build Coastguard Worker
267*8975f5c5SAndroid Build Coastguard Worker auto &streamingBuffer = (destinationIndexType == gl::DrawElementsType::UnsignedInt)
268*8975f5c5SAndroid Build Coastguard Worker ? mStreamingBufferInt
269*8975f5c5SAndroid Build Coastguard Worker : mStreamingBufferShort;
270*8975f5c5SAndroid Build Coastguard Worker
271*8975f5c5SAndroid Build Coastguard Worker if (!streamingBuffer)
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker StreamingBuffer newBuffer(new StreamingIndexBufferInterface(mFactory));
274*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(newBuffer->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
275*8975f5c5SAndroid Build Coastguard Worker destinationIndexType));
276*8975f5c5SAndroid Build Coastguard Worker streamingBuffer = std::move(newBuffer);
277*8975f5c5SAndroid Build Coastguard Worker }
278*8975f5c5SAndroid Build Coastguard Worker
279*8975f5c5SAndroid Build Coastguard Worker *outBuffer = streamingBuffer.get();
280*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
281*8975f5c5SAndroid Build Coastguard Worker }
282*8975f5c5SAndroid Build Coastguard Worker
GetIndexTranslationDestType(const gl::Context * context,GLsizei indexCount,gl::DrawElementsType indexType,const void * indices,bool usePrimitiveRestartWorkaround,gl::DrawElementsType * destTypeOut)283*8975f5c5SAndroid Build Coastguard Worker angle::Result GetIndexTranslationDestType(const gl::Context *context,
284*8975f5c5SAndroid Build Coastguard Worker GLsizei indexCount,
285*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType indexType,
286*8975f5c5SAndroid Build Coastguard Worker const void *indices,
287*8975f5c5SAndroid Build Coastguard Worker bool usePrimitiveRestartWorkaround,
288*8975f5c5SAndroid Build Coastguard Worker gl::DrawElementsType *destTypeOut)
289*8975f5c5SAndroid Build Coastguard Worker {
290*8975f5c5SAndroid Build Coastguard Worker // Avoid D3D11's primitive restart index value
291*8975f5c5SAndroid Build Coastguard Worker // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
292*8975f5c5SAndroid Build Coastguard Worker if (usePrimitiveRestartWorkaround)
293*8975f5c5SAndroid Build Coastguard Worker {
294*8975f5c5SAndroid Build Coastguard Worker // Conservatively assume we need to translate the indices for draw indirect.
295*8975f5c5SAndroid Build Coastguard Worker // This is a bit of a trick. We assume the count for an indirect draw is zero.
296*8975f5c5SAndroid Build Coastguard Worker if (indexCount == 0)
297*8975f5c5SAndroid Build Coastguard Worker {
298*8975f5c5SAndroid Build Coastguard Worker *destTypeOut = gl::DrawElementsType::UnsignedInt;
299*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
300*8975f5c5SAndroid Build Coastguard Worker }
301*8975f5c5SAndroid Build Coastguard Worker
302*8975f5c5SAndroid Build Coastguard Worker gl::IndexRange indexRange;
303*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
304*8975f5c5SAndroid Build Coastguard Worker context, indexType, indexCount, indices, &indexRange));
305*8975f5c5SAndroid Build Coastguard Worker if (indexRange.end == gl::GetPrimitiveRestartIndex(indexType))
306*8975f5c5SAndroid Build Coastguard Worker {
307*8975f5c5SAndroid Build Coastguard Worker *destTypeOut = gl::DrawElementsType::UnsignedInt;
308*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
309*8975f5c5SAndroid Build Coastguard Worker }
310*8975f5c5SAndroid Build Coastguard Worker }
311*8975f5c5SAndroid Build Coastguard Worker
312*8975f5c5SAndroid Build Coastguard Worker *destTypeOut = (indexType == gl::DrawElementsType::UnsignedInt)
313*8975f5c5SAndroid Build Coastguard Worker ? gl::DrawElementsType::UnsignedInt
314*8975f5c5SAndroid Build Coastguard Worker : gl::DrawElementsType::UnsignedShort;
315*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
316*8975f5c5SAndroid Build Coastguard Worker }
317*8975f5c5SAndroid Build Coastguard Worker
318*8975f5c5SAndroid Build Coastguard Worker } // namespace rx
319