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

Last change on this file since 2497 was 2497, checked in by sam, 7 years ago

gpu: add MeshPrimitive::Lines enum and modify the cube tutorial
to show how it can be used.

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