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