684 regels
22 KiB

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