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