686 lines
22 KiB

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