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

Last change on this file since 2030 was 2030, checked in by sam, 10 years ago

gpu: fix the computed element count in DrawIndexedElements on Direct3D.

File size: 21.4 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2012 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://sam.zoy.org/projects/COPYING.WTFPL 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    }
158#else
159    glFrontFace(GL_CCW);
160    glEnable(GL_CULL_FACE);
161#   if defined HAVE_GL_2X && !defined __APPLE__
162    /* FIXME: this has nothing to do here! */
163    glEnable(GL_ALPHA_TEST);
164    glAlphaFunc(GL_GEQUAL, 0.01f);
165#   endif
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    }
184#   if defined HAVE_GL_2X && !defined __APPLE__
185    /* FIXME: this has nothing to do here! */
186    glDisable(GL_ALPHA_TEST);
187#   endif
188#endif
189}
190
191void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase,
192                                            int vskip, int vcount,
193                                            int skip, int count)
194{
195    if (count <= 0)
196        return;
197
198#if defined _XBOX || defined USE_D3D9
199    g_d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
200    g_d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
201    g_d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
202    if (FAILED(g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW)))
203        Abort();
204    switch (type)
205    {
206    case MeshPrimitive::Triangles:
207        count = count / 3;
208        if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
209                                           vbase, vskip, vcount, skip, count)))
210            Abort();
211        break;
212    case MeshPrimitive::TriangleStrips:
213        count = count - 2;
214        if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,
215                                           vbase, vskip, vcount, skip, count)))
216            Abort();
217        break;
218    case MeshPrimitive::TriangleFans:
219        count = count - 2;
220        if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN,
221                                           vbase, vskip, vcount, skip, count)))
222            Abort();
223        break;
224    case MeshPrimitive::Points:
225        if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_POINTLIST,
226                                           vbase, vskip, vcount, skip, count)))
227            Abort();
228        break;
229    }
230#else
231    glFrontFace(GL_CCW);
232    glEnable(GL_CULL_FACE);
233#   if defined HAVE_GL_2X && !defined __APPLE__
234    /* FIXME: this has nothing to do here! */
235    glEnable(GL_ALPHA_TEST);
236    glAlphaFunc(GL_GEQUAL, 0.01f);
237#   endif
238    glEnable(GL_BLEND);
239    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
240
241    switch (type)
242    {
243    case MeshPrimitive::Triangles:
244        /* FIXME: ignores most of the arguments! */
245        (void)vbase; (void)vskip; (void)vcount; (void)skip;
246        glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, 0);
247        break;
248    case MeshPrimitive::TriangleStrips:
249        /* FIXME: ignores most of the arguments! */
250        (void)vbase; (void)vskip; (void)vcount; (void)skip;
251        glDrawElements(GL_TRIANGLE_STRIP, count, GL_UNSIGNED_SHORT, 0);
252        break;
253    case MeshPrimitive::TriangleFans:
254        /* FIXME: ignores most of the arguments! */
255        (void)vbase; (void)vskip; (void)vcount; (void)skip;
256        glDrawElements(GL_TRIANGLE_FAN, count, GL_UNSIGNED_SHORT, 0);
257        break;
258    case MeshPrimitive::Points:
259        /* FIXME: ignores most of the arguments! */
260        (void)vbase; (void)vskip; (void)vcount; (void)skip;
261        glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT, 0);
262        break;
263    }
264#   if defined HAVE_GL_2X && !defined __APPLE__
265    /* FIXME: this has nothing to do here! */
266    glDisable(GL_ALPHA_TEST);
267#   endif
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    /* FIXME: only useful for VAOs? */
298    //glBindBuffer(GL_ARRAY_BUFFER, 0);
299#else
300    /* Or even: */
301    glDisableClientState(GL_VERTEX_ARRAY);
302    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
303    glDisableClientState(GL_NORMAL_ARRAY);
304    glDisableClientState(GL_COLOR_ARRAY);
305#endif
306}
307
308void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attr1,
309                                                    ShaderAttrib attr2,
310                                                    ShaderAttrib attr3,
311                                                    ShaderAttrib attr4,
312                                                    ShaderAttrib attr5,
313                                                    ShaderAttrib attr6,
314                                                    ShaderAttrib attr7,
315                                                    ShaderAttrib attr8,
316                                                    ShaderAttrib attr9,
317                                                    ShaderAttrib attr10,
318                                                    ShaderAttrib attr11,
319                                                    ShaderAttrib attr12)
320{
321    if (!vb->m_data->m_size)
322        return;
323
324#if defined _XBOX || defined USE_D3D9
325    /* Only the first item is required to know which stream this
326     * is about; the rest of the information is stored in the
327     * vertex declaration already. */
328    uint32_t usage = (attr1.m_flags >> 16) & 0xffff;
329    uint32_t index = attr1.m_flags & 0xffff;
330
331    /* Find the stream number */
332    uint32_t usage_index = 0;
333    int stream = -1;
334    for (int i = 0; i < m_count; i++)
335        if (m_streams[i].usage == usage)
336            if (usage_index++ == index)
337            {
338                stream = m_streams[i].index;
339                break;
340            }
341
342    /* Compute this stream's stride */
343    int stride = 0;
344    for (int i = 0; i < m_count; i++)
345        if (stream == m_streams[i].index)
346            stride += m_streams[i].size;
347
348    /* Now we know the stream index and the element stride */
349    /* FIXME: precompute most of the crap above! */
350    if (stream >= 0)
351    {
352        if (FAILED(g_d3ddevice->SetStreamSource(stream, vb->m_data->m_vbo, 0, stride)))
353            Abort();
354    }
355#else
356    glBindBuffer(GL_ARRAY_BUFFER, vb->m_data->m_vbo);
357    ShaderAttrib l[12] = { attr1, attr2, attr3, attr4, attr5, attr6,
358                           attr7, attr8, attr9, attr10, attr11, attr12 };
359    for (int n = 0; n < 12 && l[n].m_flags != (uint64_t)0 - 1; n++)
360    {
361        uint32_t reg = l[n].m_flags >> 32;
362        uint32_t usage = (l[n].m_flags >> 16) & 0xffff;
363        uint32_t index = l[n].m_flags & 0xffff;
364
365#   if !defined __CELLOS_LV2__
366        glEnableVertexAttribArray((GLint)reg);
367#   else
368        switch (usage)
369        {
370        case VertexUsage::Position:
371            glEnableClientState(GL_VERTEX_ARRAY);
372            break;
373        case VertexUsage::TexCoord:
374            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
375            break;
376        case VertexUsage::Normal:
377            glEnableClientState(GL_NORMAL_ARRAY);
378            break;
379        case VertexUsage::Color:
380            glEnableClientState(GL_COLOR_ARRAY);
381            break;
382        }
383#   endif
384
385        /* We need to parse the whole vertex declaration to retrieve
386         * the information. It sucks. */
387
388        int attr_index = 0;
389        /* First, find the stream index */
390        for (uint32_t usage_index = 0; attr_index < m_count; attr_index++)
391            if (m_streams[attr_index].usage == usage)
392                if (usage_index++ == index)
393                    break;
394
395        /* Now compute the stride and offset up to this stream index */
396        int stride = 0, offset = 0;
397        for (int i = 0; i < m_count; i++)
398            if (m_streams[i].index == m_streams[attr_index].index)
399            {
400                /* Remember the register used for this stream */
401                m_streams[i].reg = reg;
402
403                stride += m_streams[i].size;
404                if (i < attr_index)
405                    offset += m_streams[i].size;
406            }
407
408        /* Finally, we need to retrieve the type of the data */
409#   if !defined GL_DOUBLE
410#       define GL_DOUBLE 0
411#   endif
412        static struct { GLint size; GLenum type; } const tlut[] =
413        {
414            { 0, 0 },
415            { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* half */
416            { 1, GL_FLOAT }, { 2, GL_FLOAT }, { 3, GL_FLOAT },
417                { 4, GL_FLOAT }, /* float */
418            { 1, GL_DOUBLE }, { 2, GL_DOUBLE }, { 3, GL_DOUBLE },
419                { 4, GL_DOUBLE }, /* double */
420            { 1, GL_BYTE }, { 2, GL_BYTE }, { 3, GL_BYTE },
421                { 4, GL_BYTE }, /* int8_t */
422            { 1, GL_UNSIGNED_BYTE }, { 2, GL_UNSIGNED_BYTE },
423                { 3, GL_UNSIGNED_BYTE }, { 4, GL_UNSIGNED_BYTE }, /* uint8_t */
424            { 1, GL_SHORT }, { 2, GL_SHORT }, { 3, GL_SHORT },
425                { 4, GL_SHORT }, /* int16_t */
426            { 1, GL_UNSIGNED_SHORT }, { 2, GL_UNSIGNED_SHORT }, { 3,
427                GL_UNSIGNED_SHORT }, { 4, GL_UNSIGNED_SHORT }, /* uint16_t */
428            { 1, GL_INT }, { 2, GL_INT }, { 3, GL_INT },
429                { 4, GL_INT }, /* int32_t */
430            { 1, GL_UNSIGNED_INT }, { 2, GL_UNSIGNED_INT },
431                { 3, GL_UNSIGNED_INT }, { 4, GL_UNSIGNED_INT }, /* uint32_t */
432        };
433
434        int type_index = m_streams[attr_index].stream_type;
435        if (type_index < 0 || type_index >= (int)(sizeof(tlut) / sizeof(*tlut)))
436            type_index = 0;
437
438
439#   if !defined __CELLOS_LV2__
440        if (tlut[type_index].type == GL_FLOAT
441             || tlut[type_index].type == GL_DOUBLE
442             || tlut[type_index].type == GL_BYTE
443             || tlut[type_index].type == GL_UNSIGNED_BYTE
444#       if defined USE_GLEW && !defined __APPLE__
445             /* If this is not available, don't use it */
446             || !glVertexAttribIPointer
447#       endif
448             || false)
449        {
450            /* Normalize unsigned bytes by default, because it's usually
451             * some color information. */
452            GLboolean normalize = (tlut[type_index].type == GL_UNSIGNED_BYTE)
453                               || (tlut[type_index].type == GL_BYTE);
454            glVertexAttribPointer((GLint)reg, tlut[type_index].size,
455                                  tlut[type_index].type, normalize,
456                                  stride, (GLvoid const *)(uintptr_t)offset);
457        }
458#       if defined GL_VERSION_3_0
459        else
460        {
461            glVertexAttribIPointer((GLint)reg, tlut[type_index].size,
462                                   tlut[type_index].type,
463                                   stride, (GLvoid const *)(uintptr_t)offset);
464        }
465#       endif
466#   else
467        switch (usage)
468        {
469        case VertexUsage::Position:
470            glVertexPointer(tlut[type_index].size, tlut[type_index].type,
471                            stride, (GLvoid const *)(uintptr_t)offset);
472            break;
473        case VertexUsage::TexCoord:
474            glTexCoordPointer(tlut[type_index].size, tlut[type_index].type,
475                              stride, (GLvoid const *)(uintptr_t)offset);
476            break;
477        case VertexUsage::Normal:
478            glNormalPointer(tlut[type_index].type,
479                            stride, (GLvoid const *)(uintptr_t)offset);
480            break;
481        case VertexUsage::Color:
482            glColorPointer(tlut[type_index].size, tlut[type_index].type,
483                           stride, (GLvoid const *)(uintptr_t)offset);
484            break;
485        default:
486            Log::Error("vertex usage %d is not supported yet\n", usage);
487            break;
488        }
489#   endif
490    }
491#endif
492}
493
494void VertexDeclaration::Initialize()
495{
496#if defined _XBOX || defined USE_D3D9
497    static D3DVERTEXELEMENT9 const end_element[] = { D3DDECL_END() };
498    static D3DDECLTYPE const X = D3DDECLTYPE_UNUSED;
499    static D3DDECLTYPE const tlut[] =
500    {
501        D3DDECLTYPE_UNUSED,
502        X, D3DDECLTYPE_FLOAT16_2, X, D3DDECLTYPE_FLOAT16_4, /* half */
503        D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3,
504            D3DDECLTYPE_FLOAT4, /* float */
505        X, X, X, X, /* double */
506        X, X, X, X, /* int8_t */
507        X, X, X, D3DDECLTYPE_UBYTE4N, /* uint8_t */
508        X, D3DDECLTYPE_SHORT2N, X, D3DDECLTYPE_SHORT4N, /* int16_t */
509        X, D3DDECLTYPE_USHORT2N, X, D3DDECLTYPE_USHORT4N, /* uint16_t */
510        X, X, X, X, /* int32_t */
511        X, X, X, X, /* uint32_t */
512    };
513    static D3DDECLUSAGE const ulut[] =
514    {
515        D3DDECLUSAGE_POSITION,
516        D3DDECLUSAGE_BLENDWEIGHT,
517        D3DDECLUSAGE_BLENDINDICES,
518        D3DDECLUSAGE_NORMAL,
519        D3DDECLUSAGE_PSIZE,
520        D3DDECLUSAGE_TEXCOORD,
521        D3DDECLUSAGE_TANGENT,
522        D3DDECLUSAGE_BINORMAL,
523        D3DDECLUSAGE_TESSFACTOR,
524#if defined _XBOX
525        D3DDECLUSAGE_TEXCOORD, /* FIXME: nonexistent */
526#else
527        D3DDECLUSAGE_POSITIONT,
528#endif
529        D3DDECLUSAGE_COLOR,
530        D3DDECLUSAGE_FOG,
531        D3DDECLUSAGE_DEPTH,
532        D3DDECLUSAGE_SAMPLE,
533    };
534
535    D3DVERTEXELEMENT9 elements[12 + 1];
536    for (int n = 0; n < m_count; n++)
537    {
538        elements[n].Stream = m_streams[n].index;
539        elements[n].Offset = 0;
540        for (int i = 0; i < n; i++)
541            if (m_streams[i].index == m_streams[n].index)
542                elements[n].Offset += m_streams[i].size;
543
544        if (m_streams[n].stream_type >= 0
545             && m_streams[n].stream_type < sizeof(tlut) / sizeof(*tlut))
546            elements[n].Type = tlut[m_streams[n].stream_type];
547        else
548            elements[n].Type = D3DDECLTYPE_UNUSED;
549
550        elements[n].Method = D3DDECLMETHOD_DEFAULT;
551
552        if (m_streams[n].usage >= 0
553             && m_streams[n].usage < sizeof(ulut) / sizeof(*ulut))
554            elements[n].Usage = ulut[m_streams[n].usage];
555        else
556            elements[n].Usage = D3DDECLUSAGE_POSITION;
557
558        elements[n].UsageIndex = 0;
559        for (int i = 0; i < n; i++)
560            if (elements[i].Stream == elements[n].Stream
561                 && elements[i].Usage == elements[n].Usage)
562                elements[n].UsageIndex++;
563    }
564    elements[m_count] = end_element[0];
565
566#   if defined USE_D3D9
567    IDirect3DVertexDeclaration9 *vdecl;
568#   elif defined _XBOX
569    D3DVertexDeclaration *vdecl;
570#   endif
571
572    if (FAILED(g_d3ddevice->CreateVertexDeclaration(elements, &vdecl)))
573        Abort();
574
575    m_data = vdecl;
576#else
577
578#endif
579}
580
581void VertexDeclaration::AddStream(VertexStreamBase const &s)
582{
583    int index = m_count ? m_streams[m_count - 1].index + 1 : 0;
584
585    for (int i = 0; s.m_streams[i].size; i++)
586    {
587        m_streams[m_count].stream_type = s.m_streams[i].stream_type;
588        m_streams[m_count].usage = s.m_streams[i].usage;
589        m_streams[m_count].size = s.m_streams[i].size;
590        m_streams[m_count].index = index;
591        m_streams[m_count].reg = -1;
592        m_count++;
593    }
594}
595
596//
597// The VertexBuffer class
598// ----------------------
599//
600
601VertexBuffer::VertexBuffer(size_t size)
602  : m_data(new VertexBufferData)
603{
604    m_data->m_size = size;
605    if (!size)
606        return;
607#if defined USE_D3D9 || defined _XBOX
608    if (FAILED(g_d3ddevice->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, NULL,
609                                               D3DPOOL_MANAGED, &m_data->m_vbo, NULL)))
610        Abort();
611#else
612    glGenBuffers(1, &m_data->m_vbo);
613    m_data->m_memory = new uint8_t[size];
614#endif
615}
616
617VertexBuffer::~VertexBuffer()
618{
619    if (m_data->m_size)
620    {
621#if defined USE_D3D9 || defined _XBOX
622        if (FAILED(m_data->m_vbo->Release()))
623            Abort();
624#else
625        glDeleteBuffers(1, &m_data->m_vbo);
626        delete[] m_data->m_memory;
627#endif
628    }
629    delete m_data;
630}
631
632void *VertexBuffer::Lock(size_t offset, size_t size)
633{
634    if (!m_data->m_size)
635        return NULL;
636#if defined USE_D3D9 || defined _XBOX
637    void *ret;
638    if (FAILED(m_data->m_vbo->Lock(offset, size, (void **)&ret, 0)))
639        Abort();
640    return ret;
641#else
642    /* FIXME: is there a way to use "size"? */
643    (void)size;
644    return m_data->m_memory + offset;
645#endif
646}
647
648void VertexBuffer::Unlock()
649{
650    if (!m_data->m_size)
651        return;
652#if defined USE_D3D9 || defined _XBOX
653    if (FAILED(m_data->m_vbo->Unlock()))
654        Abort();
655#else
656    glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo);
657    glBufferData(GL_ARRAY_BUFFER, m_data->m_size, m_data->m_memory,
658                 GL_STATIC_DRAW);
659    glBindBuffer(GL_ARRAY_BUFFER, 0);
660#endif
661}
662
663} /* namespace lol */
664
Note: See TracBrowser for help on using the repository browser.