You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

393 lines
13 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 __CELLOS_LV2__ && !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. vdecl->Release();
  87. #else
  88. #endif
  89. }
  90. void VertexDeclaration::Bind()
  91. {
  92. #if defined _XBOX || defined USE_D3D9
  93. # if defined USE_D3D9
  94. IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
  95. # elif defined _XBOX
  96. D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
  97. # endif
  98. g_d3ddevice->SetVertexDeclaration(vdecl);
  99. #else
  100. /* FIXME: Nothing to do? */
  101. #endif
  102. }
  103. void VertexDeclaration::Unbind()
  104. {
  105. #if defined _XBOX || defined USE_D3D9
  106. /* FIXME: Nothing to do? */
  107. #else
  108. /* FIXME: we need to record what happens */
  109. //glDisableVertexAttribArray(m_attrib);
  110. /* FIXME: only useful for VAOs */
  111. //glBindBuffer(GL_ARRAY_BUFFER, 0);
  112. #endif
  113. }
  114. void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attr1,
  115. ShaderAttrib attr2,
  116. ShaderAttrib attr3,
  117. ShaderAttrib attr4,
  118. ShaderAttrib attr5,
  119. ShaderAttrib attr6,
  120. ShaderAttrib attr7,
  121. ShaderAttrib attr8,
  122. ShaderAttrib attr9,
  123. ShaderAttrib attr10,
  124. ShaderAttrib attr11,
  125. ShaderAttrib attr12)
  126. {
  127. #if defined _XBOX || defined USE_D3D9
  128. /* Only the first item is required to know which stream this
  129. * is about; the rest of the information is stored in the
  130. * vertex declaration already. */
  131. uint32_t usage = (attr1.m_flags >> 16) & 0xffff;
  132. uint32_t index = attr1.m_flags & 0xffff;
  133. /* Find the stream number */
  134. int usage_index = 0, stream = -1;
  135. for (int i = 0; i < m_count; i++)
  136. if (m_streams[i].usage == usage)
  137. if (usage_index++ == index)
  138. {
  139. stream = m_streams[i].index;
  140. break;
  141. }
  142. /* Compute this stream's stride */
  143. int stride = 0;
  144. for (int i = 0; i < m_count; i++)
  145. if (stream == m_streams[i].index)
  146. stride += m_streams[i].size;
  147. /* Now we know the stream index and the element stride */
  148. /* FIXME: precompute most of the crap above! */
  149. if (stream >= 0)
  150. g_d3ddevice->SetStreamSource(stream, vb->m_data->m_vbo, 0, stride);
  151. #else
  152. glBindBuffer(GL_ARRAY_BUFFER, vb->m_data->m_vbo);
  153. ShaderAttrib l[12] = { attr1, attr2, attr3, attr4, attr5, attr6,
  154. attr7, attr8, attr9, attr10, attr11, attr12 };
  155. for (int n = 0; n < 12 && l[n].m_flags != (uint64_t)0 - 1; n++)
  156. {
  157. uint32_t reg = l[n].m_flags >> 32;
  158. uint32_t usage = (l[n].m_flags >> 16) & 0xffff;
  159. uint32_t index = l[n].m_flags & 0xffff;
  160. glEnableVertexAttribArray((GLint)reg);
  161. /* We need to parse the whole vertex declaration to retrieve
  162. * the information. It sucks. */
  163. int attr_index = 0, usage_index = 0, stream = -1;
  164. /* First, find the stream index */
  165. for (; attr_index < m_count; attr_index++)
  166. if (m_streams[attr_index].usage == usage)
  167. if (usage_index++ == index)
  168. {
  169. stream = m_streams[attr_index].index;
  170. break;
  171. }
  172. /* Now compute the stride and offset up to this stream index */
  173. int stride = 0, offset = 0;
  174. for (int i = 0; i < m_count; i++)
  175. if (m_streams[i].index == m_streams[attr_index].index)
  176. {
  177. stride += m_streams[i].size;
  178. if (i < attr_index)
  179. offset += m_streams[i].size;
  180. }
  181. /* Finally, we need to retrieve the type of the data */
  182. static struct { GLint size; GLenum type; } const tlut[] =
  183. {
  184. { 0, 0 },
  185. { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* half */
  186. { 1, GL_FLOAT }, { 2, GL_FLOAT }, { 3, GL_FLOAT },
  187. { 4, GL_FLOAT }, /* float */
  188. { 1, GL_DOUBLE }, { 2, GL_DOUBLE }, { 3, GL_DOUBLE },
  189. { 4, GL_DOUBLE }, /* double */
  190. { 1, GL_BYTE }, { 2, GL_BYTE }, { 3, GL_BYTE },
  191. { 4, GL_BYTE }, /* int8_t */
  192. { 1, GL_UNSIGNED_BYTE }, { 2, GL_UNSIGNED_BYTE },
  193. { 3, GL_UNSIGNED_BYTE }, { 4, GL_UNSIGNED_BYTE }, /* uint8_t */
  194. { 1, GL_SHORT }, { 2, GL_SHORT }, { 3, GL_SHORT },
  195. { 4, GL_SHORT }, /* int16_t */
  196. { 1, GL_UNSIGNED_SHORT }, { 2, GL_UNSIGNED_SHORT }, { 3,
  197. GL_UNSIGNED_SHORT }, { 4, GL_UNSIGNED_SHORT }, /* uint16_t */
  198. { 1, GL_INT }, { 2, GL_INT }, { 3, GL_INT },
  199. { 4, GL_INT }, /* int32_t */
  200. { 1, GL_UNSIGNED_INT }, { 2, GL_UNSIGNED_INT },
  201. { 3, GL_UNSIGNED_INT }, { 4, GL_UNSIGNED_INT }, /* uint32_t */
  202. };
  203. int type_index = m_streams[attr_index].stream_type;
  204. if (type_index < 0 || type_index >= sizeof(tlut) / sizeof(*tlut))
  205. type_index = 0;
  206. Log::Error("Size %d Type %d Stride %d offset %d\n", tlut[type_index].size,
  207. tlut[type_index].type,stride,offset);
  208. glVertexAttribPointer((GLint)reg, tlut[type_index].size,
  209. tlut[type_index].type, GL_FALSE,
  210. stride, (GLvoid const *)(uintptr_t)offset);
  211. }
  212. #endif
  213. }
  214. void VertexDeclaration::Initialize()
  215. {
  216. #if defined _XBOX || defined USE_D3D9
  217. static D3DVERTEXELEMENT9 const end_element[] = { D3DDECL_END() };
  218. static D3DDECLTYPE const X = D3DDECLTYPE_UNUSED;
  219. static D3DDECLTYPE const tlut[] =
  220. {
  221. D3DDECLTYPE_UNUSED,
  222. X, D3DDECLTYPE_FLOAT16_2, X, D3DDECLTYPE_FLOAT16_4, /* half */
  223. D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3,
  224. D3DDECLTYPE_FLOAT4, /* float */
  225. X, X, X, X, /* double */
  226. X, X, X, X, /* int8_t */
  227. X, X, X, D3DDECLTYPE_UBYTE4, /* uint8_t */
  228. X, D3DDECLTYPE_SHORT2N, X, D3DDECLTYPE_SHORT4N, /* int16_t */
  229. X, D3DDECLTYPE_USHORT2N, X, D3DDECLTYPE_USHORT4N, /* uint16_t */
  230. X, X, X, X, /* int32_t */
  231. X, X, X, X, /* int64_t */
  232. };
  233. static D3DDECLUSAGE const ulut[] =
  234. {
  235. D3DDECLUSAGE_POSITION,
  236. D3DDECLUSAGE_BLENDWEIGHT,
  237. D3DDECLUSAGE_BLENDINDICES,
  238. D3DDECLUSAGE_NORMAL,
  239. D3DDECLUSAGE_PSIZE,
  240. D3DDECLUSAGE_TEXCOORD,
  241. D3DDECLUSAGE_TANGENT,
  242. D3DDECLUSAGE_BINORMAL,
  243. D3DDECLUSAGE_TESSFACTOR,
  244. D3DDECLUSAGE_POSITIONT,
  245. D3DDECLUSAGE_COLOR,
  246. D3DDECLUSAGE_FOG,
  247. D3DDECLUSAGE_DEPTH,
  248. D3DDECLUSAGE_SAMPLE,
  249. };
  250. D3DVERTEXELEMENT9 elements[12 + 1];
  251. for (int n = 0; n < m_count; n++)
  252. {
  253. elements[n].Stream = m_streams[n].index;
  254. elements[n].Offset = 0;
  255. for (int i = 0; i < n; i++)
  256. elements[n].Offset += m_streams[n].size;
  257. if (m_streams[n].stream_type >= 0
  258. && m_streams[n].stream_type < sizeof(tlut) / sizeof(*tlut))
  259. elements[n].Type = tlut[m_streams[n].stream_type];
  260. else
  261. elements[n].Type = D3DDECLTYPE_UNUSED;
  262. elements[n].Method = D3DDECLMETHOD_DEFAULT;
  263. if (m_streams[n].usage >= 0
  264. && m_streams[n].usage < sizeof(ulut) / sizeof(*ulut))
  265. elements[n].Usage = ulut[m_streams[n].usage];
  266. else
  267. elements[n].Usage = D3DDECLUSAGE_POSITION;
  268. elements[n].UsageIndex = 0;
  269. for (int i = 0; i < n; i++)
  270. if (elements[i].Stream == elements[n].Stream
  271. && elements[i].Usage == elements[n].Usage)
  272. elements[n].UsageIndex++;
  273. }
  274. elements[m_count] = end_element[0];
  275. # if defined USE_D3D9
  276. IDirect3DVertexDeclaration9 *vdecl;
  277. # elif defined _XBOX
  278. D3DVertexDeclaration *vdecl;
  279. # endif
  280. g_d3ddevice->CreateVertexDeclaration(elements, &vdecl);
  281. m_data = vdecl;
  282. #else
  283. #endif
  284. }
  285. void VertexDeclaration::AddStream(VertexStreamBase const &s)
  286. {
  287. int index = m_count ? m_streams[m_count - 1].index + 1 : 0;
  288. for (int i = 0; s.m_streams[i].size; i++)
  289. {
  290. m_streams[m_count].stream_type = s.m_streams[i].stream_type;
  291. m_streams[m_count].usage = s.m_streams[i].usage;
  292. m_streams[m_count].size = s.m_streams[i].size;
  293. m_streams[m_count].index = index;
  294. m_count++;
  295. }
  296. }
  297. //
  298. // The VertexBuffer class
  299. // ----------------------
  300. //
  301. VertexBuffer::VertexBuffer(size_t size)
  302. : m_data(new VertexBufferData)
  303. {
  304. #if defined USE_D3D9 || defined _XBOX
  305. g_d3ddevice->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, NULL,
  306. D3DPOOL_MANAGED, &m_data->m_vbo, NULL);
  307. new uint8_t[size];
  308. #elif !defined __CELLOS_LV2__ && !defined __ANDROID__
  309. glGenBuffers(1, &m_data->m_vbo);
  310. m_data->m_memory = new uint8_t[size];
  311. m_data->m_size = size;
  312. #endif
  313. }
  314. VertexBuffer::~VertexBuffer()
  315. {
  316. #if defined USE_D3D9 || defined _XBOX
  317. m_data->m_vbo->Release();
  318. #elif !defined __CELLOS_LV2__ && !defined __ANDROID__
  319. glDeleteBuffers(1, &m_data->m_vbo);
  320. delete[] m_data->m_memory;
  321. #endif
  322. }
  323. void *VertexBuffer::Lock(size_t offset, size_t size)
  324. {
  325. #if defined USE_D3D9 || defined _XBOX
  326. void *ret;
  327. if (FAILED(m_data->m_vbo->Lock(offset, size, (void **)&ret, 0)))
  328. exit(0);
  329. return ret;
  330. #elif !defined __CELLOS_LV2__ && !defined __ANDROID__
  331. return m_data->m_memory + offset;
  332. #endif
  333. }
  334. void VertexBuffer::Unlock()
  335. {
  336. #if defined USE_D3D9 || defined _XBOX
  337. m_data->m_vbo->Unlock();
  338. #elif !defined __CELLOS_LV2__ && !defined __ANDROID__
  339. glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo);
  340. glBufferData(GL_ARRAY_BUFFER, m_data->m_size, m_data->m_memory,
  341. GL_STATIC_DRAW);
  342. #endif
  343. }
  344. } /* namespace lol */