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