559 righe
17 KiB

  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. #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. #endif
  20. using namespace std;
  21. #if defined USE_D3D9
  22. extern IDirect3DDevice9 *g_d3ddevice;
  23. #elif defined _XBOX
  24. extern D3DDevice *g_d3ddevice;
  25. #endif
  26. namespace lol
  27. {
  28. //
  29. // The VertexBufferData class
  30. // --------------------------
  31. //
  32. class VertexBufferData
  33. {
  34. friend class VertexBuffer;
  35. friend class VertexDeclaration;
  36. size_t m_size;
  37. #if defined USE_D3D9
  38. IDirect3DVertexBuffer9 *m_vbo;
  39. #elif defined _XBOX
  40. D3DVertexBuffer *m_vbo;
  41. #else
  42. GLuint m_vbo;
  43. uint8_t *m_memory;
  44. #endif
  45. };
  46. //
  47. // The VertexDeclaration class
  48. // ---------------------------
  49. //
  50. VertexStreamBase const VertexStreamBase::Empty;
  51. VertexDeclaration::VertexDeclaration(VertexStreamBase const &s1,
  52. VertexStreamBase const &s2,
  53. VertexStreamBase const &s3,
  54. VertexStreamBase const &s4,
  55. VertexStreamBase const &s5,
  56. VertexStreamBase const &s6,
  57. VertexStreamBase const &s7,
  58. VertexStreamBase const &s8,
  59. VertexStreamBase const &s9,
  60. VertexStreamBase const &s10,
  61. VertexStreamBase const &s11,
  62. VertexStreamBase const &s12) : m_count(0)
  63. {
  64. if (&s1 != &VertexStreamBase::Empty) AddStream(s1);
  65. if (&s2 != &VertexStreamBase::Empty) AddStream(s2);
  66. if (&s3 != &VertexStreamBase::Empty) AddStream(s3);
  67. if (&s4 != &VertexStreamBase::Empty) AddStream(s4);
  68. if (&s5 != &VertexStreamBase::Empty) AddStream(s5);
  69. if (&s6 != &VertexStreamBase::Empty) AddStream(s6);
  70. if (&s7 != &VertexStreamBase::Empty) AddStream(s7);
  71. if (&s8 != &VertexStreamBase::Empty) AddStream(s8);
  72. if (&s9 != &VertexStreamBase::Empty) AddStream(s9);
  73. if (&s10 != &VertexStreamBase::Empty) AddStream(s10);
  74. if (&s11 != &VertexStreamBase::Empty) AddStream(s11);
  75. if (&s12 != &VertexStreamBase::Empty) AddStream(s12);
  76. Initialize();
  77. }
  78. VertexDeclaration::~VertexDeclaration()
  79. {
  80. #if defined _XBOX || defined USE_D3D9
  81. # if defined USE_D3D9
  82. IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
  83. # elif defined _XBOX
  84. D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
  85. # endif
  86. if (FAILED(vdecl->Release()))
  87. Abort();
  88. #else
  89. #endif
  90. }
  91. void VertexDeclaration::Bind()
  92. {
  93. #if defined _XBOX || defined USE_D3D9
  94. # if defined USE_D3D9
  95. IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
  96. # elif defined _XBOX
  97. D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
  98. # endif
  99. if (FAILED(g_d3ddevice->SetVertexDeclaration(vdecl)))
  100. Abort();
  101. #else
  102. /* FIXME: Nothing to do? */
  103. #endif
  104. }
  105. void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count)
  106. {
  107. if (count <= 0)
  108. return;
  109. #if defined _XBOX || defined USE_D3D9
  110. g_d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
  111. g_d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  112. g_d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  113. if (FAILED(g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW)))
  114. Abort();
  115. switch (type)
  116. {
  117. case MeshPrimitive::Triangles:
  118. if (FAILED(g_d3ddevice->DrawPrimitive(D3DPT_TRIANGLELIST, skip, count)))
  119. Abort();
  120. break;
  121. case MeshPrimitive::Points:
  122. if (FAILED(g_d3ddevice->DrawPrimitive(D3DPT_POINTLIST, skip, count)))
  123. Abort();
  124. break;
  125. }
  126. #else
  127. glFrontFace(GL_CCW);
  128. glEnable(GL_CULL_FACE);
  129. # if defined HAVE_GL_2X && !defined __APPLE__
  130. glEnable(GL_ALPHA_TEST);
  131. glAlphaFunc(GL_GEQUAL, 0.01f);
  132. # endif
  133. glEnable(GL_BLEND);
  134. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  135. switch (type)
  136. {
  137. case MeshPrimitive::Triangles:
  138. glDrawArrays(GL_TRIANGLES, skip * 3, count * 3);
  139. break;
  140. case MeshPrimitive::Points:
  141. glDrawArrays(GL_POINTS, skip, count);
  142. break;
  143. }
  144. #endif
  145. }
  146. void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase,
  147. int vskip, int vcount,
  148. int skip, int count)
  149. {
  150. if (count <= 0)
  151. return;
  152. #if defined _XBOX || defined USE_D3D9
  153. g_d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
  154. g_d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  155. g_d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  156. g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
  157. switch (type)
  158. {
  159. case MeshPrimitive::Triangles:
  160. if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vbase, vskip, vcount, skip, count)))
  161. Abort();
  162. break;
  163. case MeshPrimitive::Points:
  164. if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_POINTLIST, vbase, vskip, vcount, skip, count)))
  165. Abort();
  166. break;
  167. }
  168. #else
  169. # if defined HAVE_GL_2X && !defined __APPLE__
  170. glEnable(GL_ALPHA_TEST);
  171. glAlphaFunc(GL_GEQUAL, 0.01f);
  172. # endif
  173. glEnable(GL_BLEND);
  174. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  175. switch (type)
  176. {
  177. case MeshPrimitive::Triangles:
  178. /* FIXME: ignores most of the arguments! */
  179. glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_SHORT, 0);
  180. break;
  181. case MeshPrimitive::Points:
  182. /* FIXME: ignores most of the arguments! */
  183. glDrawElements(GL_POINTS, count, GL_UNSIGNED_SHORT, 0);
  184. break;
  185. }
  186. #endif
  187. }
  188. void VertexDeclaration::Unbind()
  189. {
  190. #if defined _XBOX || defined USE_D3D9
  191. int stream = -1;
  192. for (int i = 0; i < m_count; i++)
  193. if (m_streams[i].index != stream)
  194. {
  195. stream = m_streams[i].index;
  196. if (FAILED(g_d3ddevice->SetStreamSource(stream, 0, 0, 0)))
  197. Abort();
  198. }
  199. if (FAILED(g_d3ddevice->SetVertexDeclaration(NULL)))
  200. Abort();
  201. #else
  202. /* FIXME: we need to unbind what we bound */
  203. //glDisableVertexAttribArray(m_attrib);
  204. /* FIXME: temporary kludge */
  205. for (int i = 0; i < 12; i++)
  206. glDisableVertexAttribArray(i);
  207. /* FIXME: only useful for VAOs */
  208. //glBindBuffer(GL_ARRAY_BUFFER, 0);
  209. /* Or: */
  210. //glDisableVertexAttribArray(m_attrib);
  211. /* Or even: */
  212. //glDisableClientState(GL_VERTEX_ARRAY);
  213. #endif
  214. }
  215. void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attr1,
  216. ShaderAttrib attr2,
  217. ShaderAttrib attr3,
  218. ShaderAttrib attr4,
  219. ShaderAttrib attr5,
  220. ShaderAttrib attr6,
  221. ShaderAttrib attr7,
  222. ShaderAttrib attr8,
  223. ShaderAttrib attr9,
  224. ShaderAttrib attr10,
  225. ShaderAttrib attr11,
  226. ShaderAttrib attr12)
  227. {
  228. if (!vb->m_data->m_size)
  229. return;
  230. #if defined _XBOX || defined USE_D3D9
  231. /* Only the first item is required to know which stream this
  232. * is about; the rest of the information is stored in the
  233. * vertex declaration already. */
  234. uint32_t usage = (attr1.m_flags >> 16) & 0xffff;
  235. uint32_t index = attr1.m_flags & 0xffff;
  236. /* Find the stream number */
  237. int usage_index = 0, stream = -1;
  238. for (int i = 0; i < m_count; i++)
  239. if (m_streams[i].usage == usage)
  240. if (usage_index++ == index)
  241. {
  242. stream = m_streams[i].index;
  243. break;
  244. }
  245. /* Compute this stream's stride */
  246. int stride = 0;
  247. for (int i = 0; i < m_count; i++)
  248. if (stream == m_streams[i].index)
  249. stride += m_streams[i].size;
  250. /* Now we know the stream index and the element stride */
  251. /* FIXME: precompute most of the crap above! */
  252. if (stream >= 0)
  253. {
  254. if (FAILED(g_d3ddevice->SetStreamSource(stream, vb->m_data->m_vbo, 0, stride)))
  255. Abort();
  256. }
  257. #else
  258. glBindBuffer(GL_ARRAY_BUFFER, vb->m_data->m_vbo);
  259. ShaderAttrib l[12] = { attr1, attr2, attr3, attr4, attr5, attr6,
  260. attr7, attr8, attr9, attr10, attr11, attr12 };
  261. for (int n = 0; n < 12 && l[n].m_flags != (uint64_t)0 - 1; n++)
  262. {
  263. uint32_t reg = l[n].m_flags >> 32;
  264. uint32_t usage = (l[n].m_flags >> 16) & 0xffff;
  265. uint32_t index = l[n].m_flags & 0xffff;
  266. # if !defined __CELLOS_LV2__
  267. glEnableVertexAttribArray((GLint)reg);
  268. # else
  269. switch (usage)
  270. {
  271. case VertexUsage::Position:
  272. glEnableClientState(GL_VERTEX_ARRAY);
  273. break;
  274. case VertexUsage::Color:
  275. glEnableClientState(GL_COLOR_ARRAY);
  276. break;
  277. }
  278. # endif
  279. /* We need to parse the whole vertex declaration to retrieve
  280. * the information. It sucks. */
  281. int attr_index = 0, usage_index = 0;
  282. /* First, find the stream index */
  283. for (; attr_index < m_count; attr_index++)
  284. if (m_streams[attr_index].usage == usage)
  285. if (usage_index++ == index)
  286. break;
  287. /* Now compute the stride and offset up to this stream index */
  288. int stride = 0, offset = 0;
  289. for (int i = 0; i < m_count; i++)
  290. if (m_streams[i].index == m_streams[attr_index].index)
  291. {
  292. stride += m_streams[i].size;
  293. if (i < attr_index)
  294. offset += m_streams[i].size;
  295. }
  296. /* Finally, we need to retrieve the type of the data */
  297. # if !defined GL_DOUBLE
  298. # define GL_DOUBLE 0
  299. # endif
  300. static struct { GLint size; GLenum type; } const tlut[] =
  301. {
  302. { 0, 0 },
  303. { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* half */
  304. { 1, GL_FLOAT }, { 2, GL_FLOAT }, { 3, GL_FLOAT },
  305. { 4, GL_FLOAT }, /* float */
  306. { 1, GL_DOUBLE }, { 2, GL_DOUBLE }, { 3, GL_DOUBLE },
  307. { 4, GL_DOUBLE }, /* double */
  308. { 1, GL_BYTE }, { 2, GL_BYTE }, { 3, GL_BYTE },
  309. { 4, GL_BYTE }, /* int8_t */
  310. { 1, GL_UNSIGNED_BYTE }, { 2, GL_UNSIGNED_BYTE },
  311. { 3, GL_UNSIGNED_BYTE }, { 4, GL_UNSIGNED_BYTE }, /* uint8_t */
  312. { 1, GL_SHORT }, { 2, GL_SHORT }, { 3, GL_SHORT },
  313. { 4, GL_SHORT }, /* int16_t */
  314. { 1, GL_UNSIGNED_SHORT }, { 2, GL_UNSIGNED_SHORT }, { 3,
  315. GL_UNSIGNED_SHORT }, { 4, GL_UNSIGNED_SHORT }, /* uint16_t */
  316. { 1, GL_INT }, { 2, GL_INT }, { 3, GL_INT },
  317. { 4, GL_INT }, /* int32_t */
  318. { 1, GL_UNSIGNED_INT }, { 2, GL_UNSIGNED_INT },
  319. { 3, GL_UNSIGNED_INT }, { 4, GL_UNSIGNED_INT }, /* uint32_t */
  320. };
  321. int type_index = m_streams[attr_index].stream_type;
  322. if (type_index < 0 || type_index >= sizeof(tlut) / sizeof(*tlut))
  323. type_index = 0;
  324. /* Normalize unsigned bytes by default, because it's usually
  325. * some color information. */
  326. GLboolean normalize = (tlut[type_index].type == GL_UNSIGNED_BYTE)
  327. || (tlut[type_index].type == GL_BYTE);
  328. # if !defined __CELLOS_LV2__
  329. glVertexAttribPointer((GLint)reg, tlut[type_index].size,
  330. tlut[type_index].type, normalize,
  331. stride, (GLvoid const *)(uintptr_t)offset);
  332. # else
  333. switch (usage)
  334. {
  335. case VertexUsage::Position:
  336. glVertexPointer(tlut[type_index].size, tlut[type_index].type,
  337. stride, (GLvoid const *)(uintptr_t)offset);
  338. break;
  339. case VertexUsage::Normal:
  340. glNormalPointer(tlut[type_index].type,
  341. stride, (GLvoid const *)(uintptr_t)offset);
  342. break;
  343. case VertexUsage::Color:
  344. glColorPointer(tlut[type_index].size, tlut[type_index].type,
  345. stride, (GLvoid const *)(uintptr_t)offset);
  346. break;
  347. }
  348. # endif
  349. }
  350. #endif
  351. }
  352. void VertexDeclaration::Initialize()
  353. {
  354. #if defined _XBOX || defined USE_D3D9
  355. static D3DVERTEXELEMENT9 const end_element[] = { D3DDECL_END() };
  356. static D3DDECLTYPE const X = D3DDECLTYPE_UNUSED;
  357. static D3DDECLTYPE const tlut[] =
  358. {
  359. D3DDECLTYPE_UNUSED,
  360. X, D3DDECLTYPE_FLOAT16_2, X, D3DDECLTYPE_FLOAT16_4, /* half */
  361. D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3,
  362. D3DDECLTYPE_FLOAT4, /* float */
  363. X, X, X, X, /* double */
  364. X, X, X, X, /* int8_t */
  365. X, X, X, D3DDECLTYPE_UBYTE4N, /* uint8_t */
  366. X, D3DDECLTYPE_SHORT2N, X, D3DDECLTYPE_SHORT4N, /* int16_t */
  367. X, D3DDECLTYPE_USHORT2N, X, D3DDECLTYPE_USHORT4N, /* uint16_t */
  368. X, X, X, X, /* int32_t */
  369. X, X, X, X, /* uint32_t */
  370. };
  371. static D3DDECLUSAGE const ulut[] =
  372. {
  373. D3DDECLUSAGE_POSITION,
  374. D3DDECLUSAGE_BLENDWEIGHT,
  375. D3DDECLUSAGE_BLENDINDICES,
  376. D3DDECLUSAGE_NORMAL,
  377. D3DDECLUSAGE_PSIZE,
  378. D3DDECLUSAGE_TEXCOORD,
  379. D3DDECLUSAGE_TANGENT,
  380. D3DDECLUSAGE_BINORMAL,
  381. D3DDECLUSAGE_TESSFACTOR,
  382. #if defined _XBOX
  383. D3DDECLUSAGE_TEXCOORD, /* FIXME: nonexistent */
  384. #else
  385. D3DDECLUSAGE_POSITIONT,
  386. #endif
  387. D3DDECLUSAGE_COLOR,
  388. D3DDECLUSAGE_FOG,
  389. D3DDECLUSAGE_DEPTH,
  390. D3DDECLUSAGE_SAMPLE,
  391. };
  392. D3DVERTEXELEMENT9 elements[12 + 1];
  393. for (int n = 0; n < m_count; n++)
  394. {
  395. elements[n].Stream = m_streams[n].index;
  396. elements[n].Offset = 0;
  397. for (int i = 0; i < n; i++)
  398. if (m_streams[i].index == m_streams[n].index)
  399. elements[n].Offset += m_streams[i].size;
  400. if (m_streams[n].stream_type >= 0
  401. && m_streams[n].stream_type < sizeof(tlut) / sizeof(*tlut))
  402. elements[n].Type = tlut[m_streams[n].stream_type];
  403. else
  404. elements[n].Type = D3DDECLTYPE_UNUSED;
  405. elements[n].Method = D3DDECLMETHOD_DEFAULT;
  406. if (m_streams[n].usage >= 0
  407. && m_streams[n].usage < sizeof(ulut) / sizeof(*ulut))
  408. elements[n].Usage = ulut[m_streams[n].usage];
  409. else
  410. elements[n].Usage = D3DDECLUSAGE_POSITION;
  411. elements[n].UsageIndex = 0;
  412. for (int i = 0; i < n; i++)
  413. if (elements[i].Stream == elements[n].Stream
  414. && elements[i].Usage == elements[n].Usage)
  415. elements[n].UsageIndex++;
  416. }
  417. elements[m_count] = end_element[0];
  418. # if defined USE_D3D9
  419. IDirect3DVertexDeclaration9 *vdecl;
  420. # elif defined _XBOX
  421. D3DVertexDeclaration *vdecl;
  422. # endif
  423. if (FAILED(g_d3ddevice->CreateVertexDeclaration(elements, &vdecl)))
  424. Abort();
  425. m_data = vdecl;
  426. #else
  427. #endif
  428. }
  429. void VertexDeclaration::AddStream(VertexStreamBase const &s)
  430. {
  431. int index = m_count ? m_streams[m_count - 1].index + 1 : 0;
  432. for (int i = 0; s.m_streams[i].size; i++)
  433. {
  434. m_streams[m_count].stream_type = s.m_streams[i].stream_type;
  435. m_streams[m_count].usage = s.m_streams[i].usage;
  436. m_streams[m_count].size = s.m_streams[i].size;
  437. m_streams[m_count].index = index;
  438. m_count++;
  439. }
  440. }
  441. //
  442. // The VertexBuffer class
  443. // ----------------------
  444. //
  445. VertexBuffer::VertexBuffer(size_t size)
  446. : m_data(new VertexBufferData)
  447. {
  448. m_data->m_size = size;
  449. if (!size)
  450. return;
  451. #if defined USE_D3D9 || defined _XBOX
  452. if (FAILED(g_d3ddevice->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, NULL,
  453. D3DPOOL_MANAGED, &m_data->m_vbo, NULL)))
  454. Abort();
  455. #elif !defined __CELLOS_LV2__
  456. glGenBuffers(1, &m_data->m_vbo);
  457. m_data->m_memory = new uint8_t[size];
  458. #endif
  459. }
  460. VertexBuffer::~VertexBuffer()
  461. {
  462. if (m_data->m_size)
  463. {
  464. #if defined USE_D3D9 || defined _XBOX
  465. if (FAILED(m_data->m_vbo->Release()))
  466. Abort();
  467. #elif !defined __CELLOS_LV2__
  468. glDeleteBuffers(1, &m_data->m_vbo);
  469. delete[] m_data->m_memory;
  470. #endif
  471. }
  472. delete m_data;
  473. }
  474. void *VertexBuffer::Lock(size_t offset, size_t size)
  475. {
  476. if (!m_data->m_size)
  477. return NULL;
  478. #if defined USE_D3D9 || defined _XBOX
  479. void *ret;
  480. if (FAILED(m_data->m_vbo->Lock(offset, size, (void **)&ret, 0)))
  481. Abort();
  482. return ret;
  483. #elif !defined __CELLOS_LV2__
  484. return m_data->m_memory + offset;
  485. #endif
  486. }
  487. void VertexBuffer::Unlock()
  488. {
  489. if (!m_data->m_size)
  490. return;
  491. #if defined USE_D3D9 || defined _XBOX
  492. if (FAILED(m_data->m_vbo->Unlock()))
  493. Abort();
  494. #elif !defined __CELLOS_LV2__
  495. glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo);
  496. glBufferData(GL_ARRAY_BUFFER, m_data->m_size, m_data->m_memory,
  497. GL_STATIC_DRAW);
  498. glBindBuffer(GL_ARRAY_BUFFER, 0);
  499. #endif
  500. }
  501. } /* namespace lol */