source: trunk/src/gpu/vertexbuffer.cpp @ 2827

Last change on this file since 2827 was 2827, checked in by benlitz, 7 years ago

gpu: fixed vbo attribute binding when one of the attribute on the buffer does not exist in the shader

  • Property svn:eol-style set to LF
File size: 22.6 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://www.wtfpl.net/ for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include "core.h"
16#include "lolgl.h"
17
18#if defined _WIN32 && defined USE_D3D9
19#   define FAR
20#   define NEAR
21#   include <d3d9.h>
22#elif defined _XBOX
23#   include <xtl.h>
24#   undef near /* Fuck Microsoft */
25#   undef far /* Fuck Microsoft again */
26#endif
27
28using namespace std;
29
30namespace lol
31{
32
33//
34// The VertexBufferData class
35// --------------------------
36//
37
38class VertexBufferData
39{
40    friend class VertexBuffer;
41    friend class VertexDeclaration;
42
43    size_t m_size;
44
45#if defined USE_D3D9
46    IDirect3DDevice9 *m_dev;
47    IDirect3DVertexBuffer9 *m_vbo;
48#elif defined _XBOX
49    D3DDevice *m_dev;
50    D3DVertexBuffer *m_vbo;
51#else
52    GLuint m_vbo;
53    uint8_t *m_memory;
54#endif
55};
56
57//
58// The VertexDeclarationData class
59// -------------------------------
60//
61
62class VertexDeclarationData
63{
64    friend class VertexBuffer;
65    friend class VertexDeclaration;
66
67#if defined USE_D3D9
68    IDirect3DDevice9 *m_dev;
69    IDirect3DVertexDeclaration9 *m_vdecl;
70#elif defined _XBOX
71    D3DDevice *m_dev;
72    D3DVertexDeclaration *m_vdecl;
73#else
74#endif
75};
76
77//
78// The VertexDeclaration class
79// ---------------------------
80//
81
82VertexStreamBase const VertexStreamBase::Empty;
83
84VertexDeclaration::VertexDeclaration(VertexStreamBase const &s1,
85                                     VertexStreamBase const &s2,
86                                     VertexStreamBase const &s3,
87                                     VertexStreamBase const &s4,
88                                     VertexStreamBase const &s5,
89                                     VertexStreamBase const &s6,
90                                     VertexStreamBase const &s7,
91                                     VertexStreamBase const &s8,
92                                     VertexStreamBase const &s9,
93                                     VertexStreamBase const &s10,
94                                     VertexStreamBase const &s11,
95                                     VertexStreamBase const &s12)
96  : m_count(0),
97    m_data(new VertexDeclarationData())
98{
99    if (&s1 != &VertexStreamBase::Empty) AddStream(s1);
100    if (&s2 != &VertexStreamBase::Empty) AddStream(s2);
101    if (&s3 != &VertexStreamBase::Empty) AddStream(s3);
102    if (&s4 != &VertexStreamBase::Empty) AddStream(s4);
103    if (&s5 != &VertexStreamBase::Empty) AddStream(s5);
104    if (&s6 != &VertexStreamBase::Empty) AddStream(s6);
105    if (&s7 != &VertexStreamBase::Empty) AddStream(s7);
106    if (&s8 != &VertexStreamBase::Empty) AddStream(s8);
107    if (&s9 != &VertexStreamBase::Empty) AddStream(s9);
108    if (&s10 != &VertexStreamBase::Empty) AddStream(s10);
109    if (&s11 != &VertexStreamBase::Empty) AddStream(s11);
110    if (&s12 != &VertexStreamBase::Empty) AddStream(s12);
111    Initialize();
112}
113
114VertexDeclaration::~VertexDeclaration()
115{
116#if defined _XBOX || defined USE_D3D9
117    if (FAILED(m_data->m_vdecl->Release()))
118        Abort();
119#else
120
121#endif
122
123    delete m_data;
124}
125
126void VertexDeclaration::Bind()
127{
128#if defined _XBOX || defined USE_D3D9
129    if (FAILED(m_data->m_dev->SetVertexDeclaration(m_data->m_vdecl)))
130        Abort();
131#else
132    /* FIXME: Nothing to do? */
133#endif
134}
135
136void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count)
137{
138    if (count <= 0)
139        return;
140
141#if defined _XBOX || defined USE_D3D9
142    switch (type)
143    {
144    case MeshPrimitive::Triangles:
145        if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLELIST,
146                                                skip, count)))
147            Abort();
148        break;
149    case MeshPrimitive::TriangleStrips:
150        if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLESTRIP,
151                                                skip, count)))
152            Abort();
153        break;
154    case MeshPrimitive::TriangleFans:
155        if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLEFAN,
156                                                skip, count)))
157            Abort();
158        break;
159    case MeshPrimitive::Points:
160        if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_POINTLIST,
161                                                skip, count)))
162            Abort();
163        break;
164    case MeshPrimitive::Lines:
165        if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_LINELIST,
166                                                skip, count)))
167            Abort();
168        break;
169    }
170#else
171    /* FIXME: this has nothing to do here! */
172    switch (type)
173    {
174    case MeshPrimitive::Triangles:
175        glDrawArrays(GL_TRIANGLES, skip, count);
176        break;
177    case MeshPrimitive::TriangleStrips:
178        glDrawArrays(GL_TRIANGLE_STRIP, skip, count);
179        break;
180    case MeshPrimitive::TriangleFans:
181        glDrawArrays(GL_TRIANGLE_FAN, skip, count);
182        break;
183    case MeshPrimitive::Points:
184        glDrawArrays(GL_POINTS, skip, count);
185        break;
186    case MeshPrimitive::Lines:
187        glDrawArrays(GL_LINES, skip, count);
188        break;
189    }
190#endif
191}
192
193void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase,
194                                            int vskip, int vcount,
195                                            int skip, int count)
196{
197    if (count <= 0)
198        return;
199
200#if defined _XBOX || defined USE_D3D9
201    switch (type)
202    {
203    case MeshPrimitive::Triangles:
204        count = count / 3;
205        if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
206                                           vbase, vskip, vcount, skip, count)))
207            Abort();
208        break;
209    case MeshPrimitive::TriangleStrips:
210        count = count - 2;
211        if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,
212                                           vbase, vskip, vcount, skip, count)))
213            Abort();
214        break;
215    case MeshPrimitive::TriangleFans:
216        count = count - 2;
217        if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN,
218                                           vbase, vskip, vcount, skip, count)))
219            Abort();
220        break;
221    case MeshPrimitive::Points:
222        if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_POINTLIST,
223                                           vbase, vskip, vcount, skip, count)))
224            Abort();
225        break;
226    case MeshPrimitive::Lines:
227        if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_LINELIST,
228                                           vbase, vskip, vcount, skip, count)))
229            Abort();
230        break;
231    }
232#else
233    /* FIXME: this has nothing to do here! */
234    switch (type)
235    {
236    case MeshPrimitive::Triangles:
237        /* FIXME: ignores most of the arguments! */
238        UNUSED(vbase, vskip, vcount, skip);
239        glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, 0);
240        break;
241    case MeshPrimitive::TriangleStrips:
242        /* FIXME: ignores most of the arguments! */
243        UNUSED(vbase, vskip, vcount, skip);
244        glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_SHORT, 0);
245        break;
246    case MeshPrimitive::TriangleFans:
247        /* FIXME: ignores most of the arguments! */
248        UNUSED(vbase, vskip, vcount, skip);
249        glDrawElements(GL_TRIANGLE_FAN, count, GL_UNSIGNED_SHORT, 0);
250        break;
251    case MeshPrimitive::Points:
252        /* FIXME: ignores most of the arguments! */
253        UNUSED(vbase, vskip, vcount, skip);
254        glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT, 0);
255        break;
256    case MeshPrimitive::Lines:
257        /* FIXME: ignores most of the arguments! */
258        UNUSED(vbase, vskip, vcount, skip);
259        glDrawElements(GL_LINES, count, GL_UNSIGNED_SHORT, 0);
260        break;
261    }
262#endif
263}
264
265void VertexDeclaration::Unbind()
266{
267#if defined _XBOX || defined USE_D3D9
268    int stream = -1;
269    for (int i = 0; i < m_count; i++)
270        if (m_streams[i].index != stream)
271        {
272            stream = m_streams[i].index;
273            if (FAILED(m_data->m_dev->SetStreamSource(stream, 0, 0, 0)))
274                Abort();
275        }
276    /* "NULL is an invalid input to SetVertexDeclaration" (DX9 guide), so
277     * we just don't touch the current vertex declaration. */
278#elif !defined __CELLOS_LV2__
279    for (int i = 0; i < m_count; i++)
280    {
281        if (m_streams[i].reg >= 0)
282        {
283            for (int j = i + 1; j < m_count; j++)
284                if (m_streams[j].reg == m_streams[i].reg)
285                    m_streams[j].reg = -1;
286
287            glDisableVertexAttribArray(m_streams[i].reg);
288        }
289    }
290    glBindBuffer(GL_ARRAY_BUFFER, 0);
291#else
292    /* Or even: */
293    glDisableClientState(GL_VERTEX_ARRAY);
294    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
295    glDisableClientState(GL_NORMAL_ARRAY);
296    glDisableClientState(GL_COLOR_ARRAY);
297#endif
298}
299
300void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attr1,
301                                                    ShaderAttrib attr2,
302                                                    ShaderAttrib attr3,
303                                                    ShaderAttrib attr4,
304                                                    ShaderAttrib attr5,
305                                                    ShaderAttrib attr6,
306                                                    ShaderAttrib attr7,
307                                                    ShaderAttrib attr8,
308                                                    ShaderAttrib attr9,
309                                                    ShaderAttrib attr10,
310                                                    ShaderAttrib attr11,
311                                                    ShaderAttrib attr12)
312{
313    if (!vb->m_data->m_size)
314        return;
315
316#if defined _XBOX || defined USE_D3D9
317    /* Only the first item is required to know which stream this
318     * is about; the rest of the information is stored in the
319     * vertex declaration already. */
320    uint32_t usage = (attr1.m_flags >> 16) & 0xffff;
321    uint32_t index = attr1.m_flags & 0xffff;
322
323    /* Find the stream number */
324    uint32_t usage_index = 0;
325    int stream = -1;
326    for (int i = 0; i < m_count; i++)
327        if (m_streams[i].usage == usage)
328            if (usage_index++ == index)
329            {
330                stream = m_streams[i].index;
331                break;
332            }
333
334    /* Compute this stream's stride */
335    int stride = 0;
336    for (int i = 0; i < m_count; i++)
337        if (stream == m_streams[i].index)
338            stride += m_streams[i].size;
339
340    /* Now we know the stream index and the element stride */
341    /* FIXME: precompute most of the crap above! */
342    if (stream >= 0)
343    {
344        if (FAILED(m_data->m_dev->SetStreamSource(stream, vb->m_data->m_vbo,
345                                                  0, stride)))
346            Abort();
347    }
348#else
349    glBindBuffer(GL_ARRAY_BUFFER, vb->m_data->m_vbo);
350    ShaderAttrib l[12] = { attr1, attr2, attr3, attr4, attr5, attr6,
351                           attr7, attr8, attr9, attr10, attr11, attr12 };
352    for (int n = 0; n < 12 && l[n].m_flags != (uint64_t)0 - 1; n++)
353    {
354        uint32_t reg = l[n].m_flags >> 32;
355        uint32_t usage = (l[n].m_flags >> 16) & 0xffff;
356        uint32_t index = l[n].m_flags & 0xffff;
357
358#   if !defined __CELLOS_LV2__
359                if (reg != 0xffffffff)
360                glEnableVertexAttribArray((GLint)reg);
361#   else
362        switch (usage)
363        {
364        case VertexUsage::Position:
365            glEnableClientState(GL_VERTEX_ARRAY);
366            break;
367        case VertexUsage::TexCoord:
368        case VertexUsage::TexCoordExt:
369            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
370            break;
371        case VertexUsage::Normal:
372            glEnableClientState(GL_NORMAL_ARRAY);
373            break;
374        case VertexUsage::Color:
375            glEnableClientState(GL_COLOR_ARRAY);
376            break;
377        }
378#   endif
379
380        /* We need to parse the whole vertex declaration to retrieve
381         * the information. It sucks. */
382
383        int attr_index = 0;
384        /* First, find the stream index */
385        for (uint32_t usage_index = 0; attr_index < m_count; attr_index++)
386            if (m_streams[attr_index].usage == usage)
387                if (usage_index++ == index)
388                    break;
389
390        if (attr_index == m_count)
391        {
392            Log::Error("stream #%d with usage %x not found in declaration\n",
393                       index, usage);
394            attr_index = 0;
395        }
396
397        /* Now compute the stride and offset up to this stream index */
398        int stride = 0, offset = 0;
399        for (int i = 0; i < m_count; i++)
400            if (m_streams[i].index == m_streams[attr_index].index)
401            {
402                /* Remember the register used for this stream */
403                m_streams[i].reg = reg;
404
405                stride += m_streams[i].size;
406                if (i < attr_index)
407                    offset += m_streams[i].size;
408            }
409
410        /* Finally, we need to retrieve the type of the data */
411#   if !defined GL_DOUBLE
412#       define GL_DOUBLE 0
413#   endif
414        static struct { GLint size; GLenum type; } const tlut[] =
415        {
416            { 0, 0 },
417            { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* half */
418            { 1, GL_FLOAT }, { 2, GL_FLOAT }, { 3, GL_FLOAT },
419                { 4, GL_FLOAT }, /* float */
420            { 1, GL_DOUBLE }, { 2, GL_DOUBLE }, { 3, GL_DOUBLE },
421                { 4, GL_DOUBLE }, /* double */
422            { 1, GL_BYTE }, { 2, GL_BYTE }, { 3, GL_BYTE },
423                { 4, GL_BYTE }, /* int8_t */
424            { 1, GL_UNSIGNED_BYTE }, { 2, GL_UNSIGNED_BYTE },
425                { 3, GL_UNSIGNED_BYTE }, { 4, GL_UNSIGNED_BYTE }, /* uint8_t */
426            { 1, GL_SHORT }, { 2, GL_SHORT }, { 3, GL_SHORT },
427                { 4, GL_SHORT }, /* int16_t */
428            { 1, GL_UNSIGNED_SHORT }, { 2, GL_UNSIGNED_SHORT }, { 3,
429                GL_UNSIGNED_SHORT }, { 4, GL_UNSIGNED_SHORT }, /* uint16_t */
430            { 1, GL_INT }, { 2, GL_INT }, { 3, GL_INT },
431                { 4, GL_INT }, /* int32_t */
432            { 1, GL_UNSIGNED_INT }, { 2, GL_UNSIGNED_INT },
433                { 3, GL_UNSIGNED_INT }, { 4, GL_UNSIGNED_INT }, /* uint32_t */
434        };
435
436        int type_index = m_streams[attr_index].stream_type;
437        if (type_index < 0 || type_index >= (int)(sizeof(tlut) / sizeof(*tlut)))
438            type_index = 0;
439
440
441#   if !defined __CELLOS_LV2__
442                if (reg != 0xffffffff)
443                {
444                        if (tlut[type_index].type == GL_FLOAT
445                                 || tlut[type_index].type == GL_DOUBLE
446                                 || tlut[type_index].type == GL_BYTE
447                                 || tlut[type_index].type == GL_UNSIGNED_BYTE
448#       if defined USE_GLEW && !defined __APPLE__
449                                 /* If this is not available, don't use it */
450                                 || !glVertexAttribIPointer
451#       endif
452                                 || false)
453                        {
454                                /* Normalize unsigned bytes by default, because it's usually
455                                 * some color information. */
456                                GLboolean normalize = (tlut[type_index].type == GL_UNSIGNED_BYTE)
457                                                                   || (tlut[type_index].type == GL_BYTE);
458                                glVertexAttribPointer((GLint)reg, tlut[type_index].size,
459                                                                          tlut[type_index].type, normalize,
460                                                                          stride, (GLvoid const *)(uintptr_t)offset);
461                        }
462#       if defined GL_VERSION_3_0
463                        else
464                        {
465                                glVertexAttribIPointer((GLint)reg, tlut[type_index].size,
466                                                                           tlut[type_index].type,
467                                                                           stride, (GLvoid const *)(uintptr_t)offset);
468                        }
469#       endif
470                }
471#   else
472        switch (usage)
473        {
474        case VertexUsage::Position:
475            glVertexPointer(tlut[type_index].size, tlut[type_index].type,
476                            stride, (GLvoid const *)(uintptr_t)offset);
477            break;
478        case VertexUsage::TexCoord:
479        case VertexUsage::TexCoordExt:
480            glTexCoordPointer(tlut[type_index].size, tlut[type_index].type,
481                              stride, (GLvoid const *)(uintptr_t)offset);
482            break;
483        case VertexUsage::Normal:
484            glNormalPointer(tlut[type_index].type,
485                            stride, (GLvoid const *)(uintptr_t)offset);
486            break;
487        case VertexUsage::Color:
488            glColorPointer(tlut[type_index].size, tlut[type_index].type,
489                           stride, (GLvoid const *)(uintptr_t)offset);
490            break;
491        default:
492            Log::Error("vertex usage %d is not supported yet\n", usage);
493            break;
494        }
495#   endif
496    }
497#endif
498}
499
500void VertexDeclaration::Initialize()
501{
502#if defined _XBOX || defined USE_D3D9
503    static D3DVERTEXELEMENT9 const end_element[] = { D3DDECL_END() };
504    static D3DDECLTYPE const X = D3DDECLTYPE_UNUSED;
505    static D3DDECLTYPE const tlut[] =
506    {
507        D3DDECLTYPE_UNUSED,
508        X, D3DDECLTYPE_FLOAT16_2, X, D3DDECLTYPE_FLOAT16_4, /* half */
509        D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3,
510            D3DDECLTYPE_FLOAT4, /* float */
511        X, X, X, X, /* double */
512        X, X, X, X, /* int8_t */
513        X, X, X, D3DDECLTYPE_UBYTE4N, /* uint8_t */
514        X, D3DDECLTYPE_SHORT2N, X, D3DDECLTYPE_SHORT4N, /* int16_t */
515        X, D3DDECLTYPE_USHORT2N, X, D3DDECLTYPE_USHORT4N, /* uint16_t */
516        X, X, X, X, /* int32_t */
517        X, X, X, X, /* uint32_t */
518    };
519    static D3DDECLUSAGE const ulut[] =
520    {
521        D3DDECLUSAGE_POSITION,
522        D3DDECLUSAGE_BLENDWEIGHT,
523        D3DDECLUSAGE_BLENDINDICES,
524        D3DDECLUSAGE_NORMAL,
525        D3DDECLUSAGE_PSIZE,
526        D3DDECLUSAGE_TEXCOORD,
527        D3DDECLUSAGE_TANGENT,
528        D3DDECLUSAGE_BINORMAL,
529        D3DDECLUSAGE_TESSFACTOR,
530#if defined _XBOX
531        D3DDECLUSAGE_TEXCOORD, /* FIXME: nonexistent */
532#else
533        D3DDECLUSAGE_POSITIONT,
534#endif
535        D3DDECLUSAGE_COLOR,
536        D3DDECLUSAGE_FOG,
537        D3DDECLUSAGE_DEPTH,
538        D3DDECLUSAGE_SAMPLE,
539    };
540
541    D3DVERTEXELEMENT9 elements[12 + 1];
542    for (int n = 0; n < m_count; n++)
543    {
544        elements[n].Stream = m_streams[n].index;
545        elements[n].Offset = 0;
546        for (int i = 0; i < n; i++)
547            if (m_streams[i].index == m_streams[n].index)
548                elements[n].Offset += m_streams[i].size;
549
550        if (m_streams[n].stream_type >= 0
551             && m_streams[n].stream_type < sizeof(tlut) / sizeof(*tlut))
552            elements[n].Type = tlut[m_streams[n].stream_type];
553        else
554            elements[n].Type = D3DDECLTYPE_UNUSED;
555
556        elements[n].Method = D3DDECLMETHOD_DEFAULT;
557
558        if (m_streams[n].usage >= 0
559             && m_streams[n].usage < sizeof(ulut) / sizeof(*ulut))
560            elements[n].Usage = ulut[m_streams[n].usage];
561        else
562            elements[n].Usage = D3DDECLUSAGE_POSITION;
563
564        elements[n].UsageIndex = 0;
565        for (int i = 0; i < n; i++)
566            if (elements[i].Stream == elements[n].Stream
567                 && elements[i].Usage == elements[n].Usage)
568                elements[n].UsageIndex++;
569    }
570    elements[m_count] = end_element[0];
571
572#   if defined USE_D3D9
573    m_data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
574#   elif defined _XBOX
575    m_data->m_dev = (D3DDevice *)g_renderer->GetDevice();
576#   endif
577
578    if (FAILED(m_data->m_dev->CreateVertexDeclaration(elements,
579                                                      &m_data->m_vdecl)))
580        Abort();
581#else
582
583#endif
584}
585
586void VertexDeclaration::AddStream(VertexStreamBase const &s)
587{
588    int index = m_count ? m_streams[m_count - 1].index + 1 : 0;
589
590    for (int i = 0; s.m_streams[i].size; i++)
591    {
592        m_streams[m_count].stream_type = s.m_streams[i].stream_type;
593        m_streams[m_count].usage = s.m_streams[i].usage;
594        m_streams[m_count].size = s.m_streams[i].size;
595        m_streams[m_count].index = index;
596        m_streams[m_count].reg = -1;
597        m_count++;
598    }
599}
600
601int VertexDeclaration::GetStreamCount() const
602{
603    return m_count ? m_streams[m_count - 1].index + 1 : 0;
604}
605
606VertexStreamBase VertexDeclaration::GetStream(int index) const
607{
608    VertexStreamBase stream;
609    int n = 0;
610    int count = 0;
611
612    for (int i = 0; i < m_count; ++i)
613    {
614        if (m_streams[i].index != index)
615            continue;
616
617        switch (m_streams[i].stream_type)
618        {
619#define LOL_TYPE(T) \
620            case VertexStreamBase::Type##T: stream.AddStream<T>(n++, m_streams[i].usage); break;
621
622            LOL_TYPE(void)
623            LOL_TYPE(half)     LOL_TYPE(f16vec2) LOL_TYPE(f16vec3) LOL_TYPE(f16vec4)
624            LOL_TYPE(float)    LOL_TYPE(vec2)    LOL_TYPE(vec3)    LOL_TYPE(vec4)
625            LOL_TYPE(double)   LOL_TYPE(dvec2)   LOL_TYPE(dvec3)   LOL_TYPE(dvec4)
626            LOL_TYPE(int8_t)   LOL_TYPE(i8vec2)  LOL_TYPE(i8vec3)  LOL_TYPE(i8vec4)
627            LOL_TYPE(uint8_t)  LOL_TYPE(u8vec2)  LOL_TYPE(u8vec3)  LOL_TYPE(u8vec4)
628            LOL_TYPE(int16_t)  LOL_TYPE(i16vec2) LOL_TYPE(i16vec3) LOL_TYPE(i16vec4)
629            LOL_TYPE(uint16_t) LOL_TYPE(u16vec2) LOL_TYPE(u16vec3) LOL_TYPE(u16vec4)
630            LOL_TYPE(int32_t)  LOL_TYPE(ivec2)   LOL_TYPE(ivec3)   LOL_TYPE(ivec4)
631            LOL_TYPE(uint32_t) LOL_TYPE(uvec2)   LOL_TYPE(uvec3)   LOL_TYPE(uvec4)
632#undef LOL_TYPE
633        }
634        ++count;
635    }
636
637    while (count < 12)
638        stream.AddStream<void>(count++, VertexStreamBase::Typevoid);
639
640    return stream;
641}
642
643//
644// The VertexBuffer class
645// ----------------------
646//
647
648VertexBuffer::VertexBuffer(size_t size)
649  : m_data(new VertexBufferData)
650{
651    m_data->m_size = size;
652    if (!size)
653        return;
654#if defined USE_D3D9 || defined _XBOX
655#   if defined USE_D3D9
656    m_data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
657#   elif defined _XBOX
658    m_data->m_dev = (D3DDevice *)g_renderer->GetDevice();
659#   endif
660
661    if (FAILED(m_data->m_dev->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, nullptr,
662                                               D3DPOOL_MANAGED, &m_data->m_vbo, nullptr)))
663        Abort();
664#else
665    glGenBuffers(1, &m_data->m_vbo);
666    m_data->m_memory = new uint8_t[size];
667#endif
668}
669
670VertexBuffer::~VertexBuffer()
671{
672    if (m_data->m_size)
673    {
674#if defined USE_D3D9 || defined _XBOX
675        if (FAILED(m_data->m_vbo->Release()))
676            Abort();
677#else
678        glDeleteBuffers(1, &m_data->m_vbo);
679        delete[] m_data->m_memory;
680#endif
681    }
682    delete m_data;
683}
684
685size_t VertexBuffer::GetSize()
686{
687    return m_data->m_size;
688}
689
690void *VertexBuffer::Lock(size_t offset, size_t size)
691{
692    if (!m_data->m_size)
693        return nullptr;
694#if defined USE_D3D9 || defined _XBOX
695    void *ret;
696    if (FAILED(m_data->m_vbo->Lock(offset, size, (void **)&ret, 0)))
697        Abort();
698    return ret;
699#else
700    /* FIXME: is there a way to use "size"? */
701    UNUSED(size);
702    return m_data->m_memory + offset;
703#endif
704}
705
706void VertexBuffer::Unlock()
707{
708    if (!m_data->m_size)
709        return;
710#if defined USE_D3D9 || defined _XBOX
711    if (FAILED(m_data->m_vbo->Unlock()))
712        Abort();
713#else
714    glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo);
715    glBufferData(GL_ARRAY_BUFFER, m_data->m_size, m_data->m_memory,
716                 GL_STATIC_DRAW);
717    glBindBuffer(GL_ARRAY_BUFFER, 0);
718#endif
719}
720
721} /* namespace lol */
722
Note: See TracBrowser for help on using the repository browser.