|
1 #include "precompiled.h" |
|
2 // |
|
3 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. |
|
4 // Use of this source code is governed by a BSD-style license that can be |
|
5 // found in the LICENSE file. |
|
6 // |
|
7 |
|
8 // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. |
|
9 |
|
10 #include "libGLESv2/renderer/VertexBuffer9.h" |
|
11 #include "libGLESv2/renderer/vertexconversion.h" |
|
12 #include "libGLESv2/renderer/BufferStorage.h" |
|
13 #include "libGLESv2/Context.h" |
|
14 #include "libGLESv2/renderer/Renderer9.h" |
|
15 |
|
16 #include "libGLESv2/Buffer.h" |
|
17 |
|
18 namespace rx |
|
19 { |
|
20 |
|
21 bool VertexBuffer9::mTranslationsInitialized = false; |
|
22 VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; |
|
23 |
|
24 VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) |
|
25 { |
|
26 mVertexBuffer = NULL; |
|
27 mBufferSize = 0; |
|
28 mDynamicUsage = false; |
|
29 |
|
30 if (!mTranslationsInitialized) |
|
31 { |
|
32 initializeTranslations(renderer->getCapsDeclTypes()); |
|
33 mTranslationsInitialized = true; |
|
34 } |
|
35 } |
|
36 |
|
37 VertexBuffer9::~VertexBuffer9() |
|
38 { |
|
39 if (mVertexBuffer) |
|
40 { |
|
41 mVertexBuffer->Release(); |
|
42 mVertexBuffer = NULL; |
|
43 } |
|
44 } |
|
45 |
|
46 bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) |
|
47 { |
|
48 if (mVertexBuffer) |
|
49 { |
|
50 mVertexBuffer->Release(); |
|
51 mVertexBuffer = NULL; |
|
52 } |
|
53 |
|
54 updateSerial(); |
|
55 |
|
56 if (size > 0) |
|
57 { |
|
58 DWORD flags = D3DUSAGE_WRITEONLY; |
|
59 if (dynamicUsage) |
|
60 { |
|
61 flags |= D3DUSAGE_DYNAMIC; |
|
62 } |
|
63 |
|
64 HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); |
|
65 |
|
66 if (FAILED(result)) |
|
67 { |
|
68 ERR("Out of memory allocating a vertex buffer of size %lu.", size); |
|
69 return false; |
|
70 } |
|
71 } |
|
72 |
|
73 mBufferSize = size; |
|
74 mDynamicUsage = dynamicUsage; |
|
75 return true; |
|
76 } |
|
77 |
|
78 VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) |
|
79 { |
|
80 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); |
|
81 return static_cast<VertexBuffer9*>(vertexBuffer); |
|
82 } |
|
83 |
|
84 bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, |
|
85 GLsizei instances, unsigned int offset) |
|
86 { |
|
87 if (mVertexBuffer) |
|
88 { |
|
89 gl::Buffer *buffer = attrib.mBoundBuffer.get(); |
|
90 |
|
91 int inputStride = attrib.stride(); |
|
92 int elementSize = attrib.typeSize(); |
|
93 const FormatConverter &converter = formatConverter(attrib); |
|
94 |
|
95 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; |
|
96 |
|
97 void *mapPtr = NULL; |
|
98 |
|
99 unsigned int mapSize; |
|
100 if (!spaceRequired(attrib, count, instances, &mapSize)) |
|
101 { |
|
102 return false; |
|
103 } |
|
104 |
|
105 HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); |
|
106 |
|
107 if (FAILED(result)) |
|
108 { |
|
109 ERR("Lock failed with error 0x%08x", result); |
|
110 return false; |
|
111 } |
|
112 |
|
113 const char *input = NULL; |
|
114 if (buffer) |
|
115 { |
|
116 BufferStorage *storage = buffer->getStorage(); |
|
117 input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset); |
|
118 } |
|
119 else |
|
120 { |
|
121 input = static_cast<const char*>(attrib.mPointer); |
|
122 } |
|
123 |
|
124 if (instances == 0 || attrib.mDivisor == 0) |
|
125 { |
|
126 input += inputStride * start; |
|
127 } |
|
128 |
|
129 if (converter.identity && inputStride == elementSize) |
|
130 { |
|
131 memcpy(mapPtr, input, count * inputStride); |
|
132 } |
|
133 else |
|
134 { |
|
135 converter.convertArray(input, inputStride, count, mapPtr); |
|
136 } |
|
137 |
|
138 mVertexBuffer->Unlock(); |
|
139 |
|
140 return true; |
|
141 } |
|
142 else |
|
143 { |
|
144 ERR("Vertex buffer not initialized."); |
|
145 return false; |
|
146 } |
|
147 } |
|
148 |
|
149 bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset) |
|
150 { |
|
151 if (mVertexBuffer) |
|
152 { |
|
153 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; |
|
154 |
|
155 void *mapPtr = NULL; |
|
156 HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags); |
|
157 |
|
158 if (FAILED(result)) |
|
159 { |
|
160 ERR("Lock failed with error 0x%08x", result); |
|
161 return false; |
|
162 } |
|
163 |
|
164 memcpy(mapPtr, data, size); |
|
165 |
|
166 mVertexBuffer->Unlock(); |
|
167 |
|
168 return true; |
|
169 } |
|
170 else |
|
171 { |
|
172 ERR("Vertex buffer not initialized."); |
|
173 return false; |
|
174 } |
|
175 } |
|
176 |
|
177 bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, |
|
178 unsigned int *outSpaceRequired) const |
|
179 { |
|
180 return spaceRequired(attrib, count, instances, outSpaceRequired); |
|
181 } |
|
182 |
|
183 bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const |
|
184 { |
|
185 return formatConverter(attrib).identity; |
|
186 } |
|
187 |
|
188 unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const |
|
189 { |
|
190 unsigned int spaceRequired; |
|
191 return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0; |
|
192 } |
|
193 |
|
194 D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const |
|
195 { |
|
196 return formatConverter(attrib).d3dDeclType; |
|
197 } |
|
198 |
|
199 unsigned int VertexBuffer9::getBufferSize() const |
|
200 { |
|
201 return mBufferSize; |
|
202 } |
|
203 |
|
204 bool VertexBuffer9::setBufferSize(unsigned int size) |
|
205 { |
|
206 if (size > mBufferSize) |
|
207 { |
|
208 return initialize(size, mDynamicUsage); |
|
209 } |
|
210 else |
|
211 { |
|
212 return true; |
|
213 } |
|
214 } |
|
215 |
|
216 bool VertexBuffer9::discard() |
|
217 { |
|
218 if (mVertexBuffer) |
|
219 { |
|
220 void *dummy; |
|
221 HRESULT result; |
|
222 |
|
223 result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); |
|
224 if (FAILED(result)) |
|
225 { |
|
226 ERR("Discard lock failed with error 0x%08x", result); |
|
227 return false; |
|
228 } |
|
229 |
|
230 result = mVertexBuffer->Unlock(); |
|
231 if (FAILED(result)) |
|
232 { |
|
233 ERR("Discard unlock failed with error 0x%08x", result); |
|
234 return false; |
|
235 } |
|
236 |
|
237 return true; |
|
238 } |
|
239 else |
|
240 { |
|
241 ERR("Vertex buffer not initialized."); |
|
242 return false; |
|
243 } |
|
244 } |
|
245 |
|
246 IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const |
|
247 { |
|
248 return mVertexBuffer; |
|
249 } |
|
250 |
|
251 // Mapping from OpenGL-ES vertex attrib type to D3D decl type: |
|
252 // |
|
253 // BYTE SHORT (Cast) |
|
254 // BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) |
|
255 // UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) |
|
256 // UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) |
|
257 // SHORT SHORT (Identity) |
|
258 // SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) |
|
259 // UNSIGNED_SHORT FLOAT (Cast) |
|
260 // UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) |
|
261 // FIXED (not in WebGL) FLOAT (FixedToFloat) |
|
262 // FLOAT FLOAT (Identity) |
|
263 |
|
264 // GLToCType maps from GL type (as GLenum) to the C typedef. |
|
265 template <GLenum GLType> struct GLToCType { }; |
|
266 |
|
267 template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; }; |
|
268 template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; }; |
|
269 template <> struct GLToCType<GL_SHORT> { typedef GLshort type; }; |
|
270 template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; }; |
|
271 template <> struct GLToCType<GL_FIXED> { typedef GLuint type; }; |
|
272 template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; }; |
|
273 |
|
274 // This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.) |
|
275 enum D3DVertexType |
|
276 { |
|
277 D3DVT_FLOAT, |
|
278 D3DVT_SHORT, |
|
279 D3DVT_SHORT_NORM, |
|
280 D3DVT_UBYTE, |
|
281 D3DVT_UBYTE_NORM, |
|
282 D3DVT_USHORT_NORM |
|
283 }; |
|
284 |
|
285 // D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type. |
|
286 template <unsigned int D3DType> struct D3DToCType { }; |
|
287 |
|
288 template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; }; |
|
289 template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; }; |
|
290 template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; }; |
|
291 template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; }; |
|
292 template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; }; |
|
293 template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; }; |
|
294 |
|
295 // Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size. |
|
296 template <unsigned int type, int size> struct WidenRule { }; |
|
297 |
|
298 template <int size> struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size> { }; |
|
299 template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { }; |
|
300 template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { }; |
|
301 template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { }; |
|
302 template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { }; |
|
303 template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size> { }; |
|
304 |
|
305 // VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. |
|
306 template <unsigned int d3dtype, int size> struct VertexTypeFlags { }; |
|
307 |
|
308 template <unsigned int _capflag, unsigned int _declflag> |
|
309 struct VertexTypeFlagsHelper |
|
310 { |
|
311 enum { capflag = _capflag }; |
|
312 enum { declflag = _declflag }; |
|
313 }; |
|
314 |
|
315 template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; |
|
316 template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; |
|
317 template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; |
|
318 template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; |
|
319 template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; |
|
320 template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; |
|
321 template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { }; |
|
322 template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { }; |
|
323 template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { }; |
|
324 template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { }; |
|
325 template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { }; |
|
326 template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { }; |
|
327 |
|
328 |
|
329 // VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). |
|
330 template <GLenum GLtype, bool normalized> struct VertexTypeMapping { }; |
|
331 |
|
332 template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred> |
|
333 struct VertexTypeMappingBase |
|
334 { |
|
335 enum { preferred = Preferred }; |
|
336 enum { fallback = Fallback }; |
|
337 }; |
|
338 |
|
339 template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast |
|
340 template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize |
|
341 template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast |
|
342 template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize |
|
343 template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity |
|
344 template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize |
|
345 template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast |
|
346 template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize |
|
347 template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat |
|
348 template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity |
|
349 |
|
350 |
|
351 // Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat). |
|
352 // The conversion rules themselves are defined in vertexconversion.h. |
|
353 |
|
354 // Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping). |
|
355 template <GLenum fromType, bool normalized, unsigned int toType> |
|
356 struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { }; |
|
357 |
|
358 // All conversions from normalized types to float use the Normalize operator. |
|
359 template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { }; |
|
360 |
|
361 // Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. |
|
362 template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { }; |
|
363 template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { }; |
|
364 |
|
365 // A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) |
|
366 // whether it is normalized or not. |
|
367 template <class T, bool normalized> struct DefaultVertexValuesStage2 { }; |
|
368 |
|
369 template <class T> struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T> { }; |
|
370 template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { }; |
|
371 |
|
372 // Work out the default value rule for a D3D type (expressed as the C type) and |
|
373 template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { }; |
|
374 template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { }; |
|
375 |
|
376 // Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion. |
|
377 // The fallback conversion produces an output that all D3D9 devices must support. |
|
378 template <class T> struct UsePreferred { enum { type = T::preferred }; }; |
|
379 template <class T> struct UseFallback { enum { type = T::fallback }; }; |
|
380 |
|
381 // Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion, |
|
382 // it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag |
|
383 // and the D3DDECLTYPE member needed for the vertex declaration in declflag. |
|
384 template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule> |
|
385 struct Converter |
|
386 : VertexDataConverter<typename GLToCType<fromType>::type, |
|
387 WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>, |
|
388 ConversionRule<fromType, |
|
389 normalized, |
|
390 PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>, |
|
391 DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > > |
|
392 { |
|
393 private: |
|
394 enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type }; |
|
395 enum { d3dsize = WidenRule<d3dtype, size>::finalWidth }; |
|
396 |
|
397 public: |
|
398 enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag }; |
|
399 enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag }; |
|
400 }; |
|
401 |
|
402 // Initialize a TranslationInfo |
|
403 #define TRANSLATION(type, norm, size, preferred) \ |
|
404 { \ |
|
405 Converter<type, norm, size, preferred>::identity, \ |
|
406 Converter<type, norm, size, preferred>::finalSize, \ |
|
407 Converter<type, norm, size, preferred>::convertArray, \ |
|
408 static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \ |
|
409 } |
|
410 |
|
411 #define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ |
|
412 { \ |
|
413 Converter<type, norm, size, UsePreferred>::capflag, \ |
|
414 TRANSLATION(type, norm, size, UsePreferred), \ |
|
415 TRANSLATION(type, norm, size, UseFallback) \ |
|
416 } |
|
417 |
|
418 #define TRANSLATIONS_FOR_TYPE(type) \ |
|
419 { \ |
|
420 { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ |
|
421 { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \ |
|
422 } |
|
423 |
|
424 #define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ |
|
425 { \ |
|
426 { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ |
|
427 { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ |
|
428 } |
|
429 |
|
430 const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] |
|
431 { |
|
432 TRANSLATIONS_FOR_TYPE(GL_BYTE), |
|
433 TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), |
|
434 TRANSLATIONS_FOR_TYPE(GL_SHORT), |
|
435 TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), |
|
436 TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), |
|
437 TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) |
|
438 }; |
|
439 |
|
440 void VertexBuffer9::initializeTranslations(DWORD declTypes) |
|
441 { |
|
442 for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) |
|
443 { |
|
444 for (unsigned int j = 0; j < 2; j++) |
|
445 { |
|
446 for (unsigned int k = 0; k < 4; k++) |
|
447 { |
|
448 if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) |
|
449 { |
|
450 mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; |
|
451 } |
|
452 else |
|
453 { |
|
454 mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; |
|
455 } |
|
456 } |
|
457 } |
|
458 } |
|
459 } |
|
460 |
|
461 unsigned int VertexBuffer9::typeIndex(GLenum type) |
|
462 { |
|
463 switch (type) |
|
464 { |
|
465 case GL_BYTE: return 0; |
|
466 case GL_UNSIGNED_BYTE: return 1; |
|
467 case GL_SHORT: return 2; |
|
468 case GL_UNSIGNED_SHORT: return 3; |
|
469 case GL_FIXED: return 4; |
|
470 case GL_FLOAT: return 5; |
|
471 |
|
472 default: UNREACHABLE(); return 5; |
|
473 } |
|
474 } |
|
475 |
|
476 const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute) |
|
477 { |
|
478 return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; |
|
479 } |
|
480 |
|
481 bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, |
|
482 unsigned int *outSpaceRequired) |
|
483 { |
|
484 unsigned int elementSize = formatConverter(attrib).outputElementSize; |
|
485 |
|
486 if (instances == 0 || attrib.mDivisor == 0) |
|
487 { |
|
488 unsigned int elementCount = 0; |
|
489 if (instances == 0 || attrib.mDivisor == 0) |
|
490 { |
|
491 elementCount = count; |
|
492 } |
|
493 else |
|
494 { |
|
495 if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1)) |
|
496 { |
|
497 // Round up |
|
498 elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; |
|
499 } |
|
500 else |
|
501 { |
|
502 elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor; |
|
503 } |
|
504 } |
|
505 |
|
506 if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount) |
|
507 { |
|
508 if (outSpaceRequired) |
|
509 { |
|
510 *outSpaceRequired = elementSize * elementCount; |
|
511 } |
|
512 return true; |
|
513 } |
|
514 else |
|
515 { |
|
516 return false; |
|
517 } |
|
518 } |
|
519 else |
|
520 { |
|
521 const unsigned int elementSize = 4; |
|
522 if (outSpaceRequired) |
|
523 { |
|
524 *outSpaceRequired = elementSize * 4; |
|
525 } |
|
526 return true; |
|
527 } |
|
528 } |
|
529 |
|
530 } |