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