392 líneas
12 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2016 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include "lolgl.h"
  14. namespace lol
  15. {
  16. //
  17. // The VertexBufferData class
  18. // --------------------------
  19. //
  20. class VertexBufferData
  21. {
  22. friend class VertexBuffer;
  23. friend class VertexDeclaration;
  24. size_t m_size;
  25. GLuint m_vbo;
  26. uint8_t *m_memory;
  27. };
  28. //
  29. // The VertexDeclaration class
  30. // ---------------------------
  31. //
  32. VertexStreamBase const VertexStreamBase::Empty;
  33. VertexDeclaration::VertexDeclaration(VertexStreamBase const &s1,
  34. VertexStreamBase const &s2,
  35. VertexStreamBase const &s3,
  36. VertexStreamBase const &s4,
  37. VertexStreamBase const &s5,
  38. VertexStreamBase const &s6,
  39. VertexStreamBase const &s7,
  40. VertexStreamBase const &s8,
  41. VertexStreamBase const &s9,
  42. VertexStreamBase const &s10,
  43. VertexStreamBase const &s11,
  44. VertexStreamBase const &s12)
  45. : m_count(0)
  46. {
  47. if (&s1 != &VertexStreamBase::Empty) AddStream(s1);
  48. if (&s2 != &VertexStreamBase::Empty) AddStream(s2);
  49. if (&s3 != &VertexStreamBase::Empty) AddStream(s3);
  50. if (&s4 != &VertexStreamBase::Empty) AddStream(s4);
  51. if (&s5 != &VertexStreamBase::Empty) AddStream(s5);
  52. if (&s6 != &VertexStreamBase::Empty) AddStream(s6);
  53. if (&s7 != &VertexStreamBase::Empty) AddStream(s7);
  54. if (&s8 != &VertexStreamBase::Empty) AddStream(s8);
  55. if (&s9 != &VertexStreamBase::Empty) AddStream(s9);
  56. if (&s10 != &VertexStreamBase::Empty) AddStream(s10);
  57. if (&s11 != &VertexStreamBase::Empty) AddStream(s11);
  58. if (&s12 != &VertexStreamBase::Empty) AddStream(s12);
  59. }
  60. VertexDeclaration::~VertexDeclaration()
  61. {
  62. }
  63. void VertexDeclaration::Bind()
  64. {
  65. /* FIXME: Nothing to do? */
  66. }
  67. void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count)
  68. {
  69. if (count <= 0)
  70. return;
  71. /* FIXME: this has nothing to do here! */
  72. switch (type.ToScalar())
  73. {
  74. case MeshPrimitive::Triangles:
  75. glDrawArrays(GL_TRIANGLES, skip, count);
  76. break;
  77. case MeshPrimitive::TriangleStrips:
  78. glDrawArrays(GL_TRIANGLE_STRIP, skip, count);
  79. break;
  80. case MeshPrimitive::TriangleFans:
  81. glDrawArrays(GL_TRIANGLE_FAN, skip, count);
  82. break;
  83. case MeshPrimitive::Points:
  84. glDrawArrays(GL_POINTS, skip, count);
  85. break;
  86. case MeshPrimitive::Lines:
  87. glDrawArrays(GL_LINES, skip, count);
  88. break;
  89. }
  90. }
  91. void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int count, const short* skip, short typeSize)
  92. {
  93. if (count <= 0)
  94. return;
  95. uint32_t elementType = typeSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
  96. /* FIXME: this has nothing to do here! */
  97. switch (type.ToScalar())
  98. {
  99. case MeshPrimitive::Triangles:
  100. glDrawElements(GL_TRIANGLES, count, elementType, skip);
  101. break;
  102. case MeshPrimitive::TriangleStrips:
  103. glDrawElements(GL_TRIANGLE_STRIP, count, elementType, skip);
  104. break;
  105. case MeshPrimitive::TriangleFans:
  106. glDrawElements(GL_TRIANGLE_FAN, count, elementType, skip);
  107. break;
  108. case MeshPrimitive::Points:
  109. glDrawElements(GL_POINTS, count, elementType, skip);
  110. break;
  111. case MeshPrimitive::Lines:
  112. glDrawElements(GL_LINES, count, elementType, skip);
  113. break;
  114. }
  115. }
  116. void VertexDeclaration::Unbind()
  117. {
  118. for (int i = 0; i < m_count; i++)
  119. {
  120. if (m_streams[i].reg >= 0)
  121. {
  122. for (int j = i + 1; j < m_count; j++)
  123. if (m_streams[j].reg == m_streams[i].reg)
  124. m_streams[j].reg = -1;
  125. glDisableVertexAttribArray(m_streams[i].reg);
  126. }
  127. }
  128. glBindBuffer(GL_ARRAY_BUFFER, 0);
  129. }
  130. void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attr1,
  131. ShaderAttrib attr2,
  132. ShaderAttrib attr3,
  133. ShaderAttrib attr4,
  134. ShaderAttrib attr5,
  135. ShaderAttrib attr6,
  136. ShaderAttrib attr7,
  137. ShaderAttrib attr8,
  138. ShaderAttrib attr9,
  139. ShaderAttrib attr10,
  140. ShaderAttrib attr11,
  141. ShaderAttrib attr12)
  142. {
  143. ShaderAttrib attribs[12] = { attr1, attr2, attr3, attr4, attr5, attr6,
  144. attr7, attr8, attr9, attr10, attr11, attr12 };
  145. SetStream(vb, attribs);
  146. }
  147. void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attribs[])
  148. {
  149. if (!vb->m_data->m_size)
  150. return;
  151. glBindBuffer(GL_ARRAY_BUFFER, vb->m_data->m_vbo);
  152. for (int n = 0; n < 12 && attribs[n].m_flags != (uint64_t)0 - 1; n++)
  153. {
  154. VertexUsage usage = VertexUsage((attribs[n].m_flags >> 16) & 0xffff);
  155. uint32_t index = attribs[n].m_flags & 0xffff;
  156. uint32_t reg = attribs[n].m_flags >> 32;
  157. if (reg != 0xffffffffu)
  158. glEnableVertexAttribArray((GLint)reg);
  159. /* We need to parse the whole vertex declaration to retrieve
  160. * the information. It sucks. */
  161. int attr_index = 0;
  162. /* First, find the stream index */
  163. for (uint32_t usage_index = 0; attr_index < m_count; attr_index++)
  164. if (m_streams[attr_index].usage == usage)
  165. if (usage_index++ == index)
  166. break;
  167. if (attr_index == m_count)
  168. {
  169. msg::error("stream #%d with usage %x not found in declaration\n",
  170. index, usage.ToScalar());
  171. attr_index = 0;
  172. }
  173. /* Now compute the stride and offset up to this stream index */
  174. int stride = 0, offset = 0;
  175. for (int i = 0; i < m_count; i++)
  176. if (m_streams[i].index == m_streams[attr_index].index)
  177. {
  178. /* Remember the register used for this stream */
  179. m_streams[i].reg = reg;
  180. stride += m_streams[i].size;
  181. if (i < attr_index)
  182. offset += m_streams[i].size;
  183. }
  184. /* Finally, we need to retrieve the type of the data */
  185. #if !defined GL_DOUBLE
  186. # define GL_DOUBLE 0
  187. #endif
  188. static struct { GLint size; GLenum type; } const tlut[] =
  189. {
  190. { 0, 0 },
  191. #if LOL_FEATURE_CXX11_UNRESTRICTED_UNIONS
  192. { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* half */
  193. #endif
  194. { 1, GL_FLOAT }, { 2, GL_FLOAT }, { 3, GL_FLOAT },
  195. { 4, GL_FLOAT }, /* float */
  196. { 1, GL_DOUBLE }, { 2, GL_DOUBLE }, { 3, GL_DOUBLE },
  197. { 4, GL_DOUBLE }, /* double */
  198. { 1, GL_BYTE }, { 2, GL_BYTE }, { 3, GL_BYTE },
  199. { 4, GL_BYTE }, /* int8_t */
  200. { 1, GL_UNSIGNED_BYTE }, { 2, GL_UNSIGNED_BYTE },
  201. { 3, GL_UNSIGNED_BYTE }, { 4, GL_UNSIGNED_BYTE }, /* uint8_t */
  202. { 1, GL_SHORT }, { 2, GL_SHORT }, { 3, GL_SHORT },
  203. { 4, GL_SHORT }, /* int16_t */
  204. { 1, GL_UNSIGNED_SHORT }, { 2, GL_UNSIGNED_SHORT }, { 3,
  205. GL_UNSIGNED_SHORT }, { 4, GL_UNSIGNED_SHORT }, /* uint16_t */
  206. { 1, GL_INT }, { 2, GL_INT }, { 3, GL_INT },
  207. { 4, GL_INT }, /* int32_t */
  208. { 1, GL_UNSIGNED_INT }, { 2, GL_UNSIGNED_INT },
  209. { 3, GL_UNSIGNED_INT }, { 4, GL_UNSIGNED_INT }, /* uint32_t */
  210. };
  211. int type_index = m_streams[attr_index].stream_type;
  212. if (type_index < 0 || type_index >= (int)(sizeof(tlut) / sizeof(*tlut)))
  213. type_index = 0;
  214. if (reg != 0xffffffff)
  215. {
  216. if (tlut[type_index].type == GL_FLOAT
  217. || tlut[type_index].type == GL_DOUBLE
  218. || tlut[type_index].type == GL_BYTE
  219. || tlut[type_index].type == GL_UNSIGNED_BYTE
  220. #if defined LOL_USE_GLEW && !defined __APPLE__
  221. /* If this is not available, don't use it */
  222. || !glVertexAttribIPointer
  223. #endif
  224. || false)
  225. {
  226. /* Normalize unsigned bytes by default, because it's usually
  227. * some color information. */
  228. GLboolean normalize = (tlut[type_index].type == GL_UNSIGNED_BYTE)
  229. || (tlut[type_index].type == GL_BYTE);
  230. glVertexAttribPointer((GLint)reg, tlut[type_index].size,
  231. tlut[type_index].type, normalize,
  232. stride, (GLvoid const *)(uintptr_t)offset);
  233. }
  234. #if defined GL_VERSION_3_0
  235. else
  236. {
  237. glVertexAttribIPointer((GLint)reg, tlut[type_index].size,
  238. tlut[type_index].type,
  239. stride, (GLvoid const *)(uintptr_t)offset);
  240. }
  241. #endif
  242. }
  243. }
  244. }
  245. void VertexDeclaration::AddStream(VertexStreamBase const &s)
  246. {
  247. int index = m_count ? m_streams[m_count - 1].index + 1 : 0;
  248. for (int i = 0; s.m_streams[i].size; i++)
  249. {
  250. m_streams[m_count].stream_type = s.m_streams[i].stream_type;
  251. m_streams[m_count].usage = s.m_streams[i].usage;
  252. m_streams[m_count].size = s.m_streams[i].size;
  253. m_streams[m_count].index = index;
  254. m_streams[m_count].reg = -1;
  255. m_count++;
  256. }
  257. }
  258. int VertexDeclaration::GetStreamCount() const
  259. {
  260. return m_count ? m_streams[m_count - 1].index + 1 : 0;
  261. }
  262. VertexStreamBase VertexDeclaration::GetStream(int index) const
  263. {
  264. VertexStreamBase stream;
  265. int n = 0;
  266. int count = 0;
  267. for (int i = 0; i < m_count; ++i)
  268. {
  269. if (m_streams[i].index != index)
  270. continue;
  271. switch (m_streams[i].stream_type)
  272. {
  273. #define __T(T) \
  274. case VertexStreamBase::Type##T: stream.AddStream<T>(n++, m_streams[i].usage); break;
  275. __T(void)
  276. #if LOL_FEATURE_CXX11_UNRESTRICTED_UNIONS
  277. __T(half) __T(f16vec2) __T(f16vec3) __T(f16vec4)
  278. #endif
  279. __T(float) __T(vec2) __T(vec3) __T(vec4)
  280. __T(double) __T(dvec2) __T(dvec3) __T(dvec4)
  281. __T(int8_t) __T(i8vec2) __T(i8vec3) __T(i8vec4)
  282. __T(uint8_t) __T(u8vec2) __T(u8vec3) __T(u8vec4)
  283. __T(int16_t) __T(i16vec2) __T(i16vec3) __T(i16vec4)
  284. __T(uint16_t) __T(u16vec2) __T(u16vec3) __T(u16vec4)
  285. __T(int32_t) __T(ivec2) __T(ivec3) __T(ivec4)
  286. __T(uint32_t) __T(uvec2) __T(uvec3) __T(uvec4)
  287. #undef __T
  288. }
  289. ++count;
  290. }
  291. while (count < 12)
  292. stream.AddStream<void>(count++, VertexUsage::Position);
  293. return stream;
  294. }
  295. //
  296. // The VertexBuffer class
  297. // ----------------------
  298. //
  299. VertexBuffer::VertexBuffer(size_t size)
  300. : m_data(new VertexBufferData)
  301. {
  302. m_data->m_size = size;
  303. if (!size)
  304. return;
  305. glGenBuffers(1, &m_data->m_vbo);
  306. m_data->m_memory = new uint8_t[size];
  307. }
  308. VertexBuffer::~VertexBuffer()
  309. {
  310. if (m_data->m_size)
  311. {
  312. glDeleteBuffers(1, &m_data->m_vbo);
  313. delete[] m_data->m_memory;
  314. }
  315. delete m_data;
  316. }
  317. size_t VertexBuffer::GetSize()
  318. {
  319. return m_data->m_size;
  320. }
  321. void *VertexBuffer::Lock(size_t offset, size_t size)
  322. {
  323. if (!m_data->m_size)
  324. return nullptr;
  325. /* FIXME: is there a way to use "size"? */
  326. UNUSED(size);
  327. return m_data->m_memory + offset;
  328. }
  329. void VertexBuffer::Unlock()
  330. {
  331. if (!m_data->m_size)
  332. return;
  333. glBindBuffer(GL_ARRAY_BUFFER, m_data->m_vbo);
  334. glBufferData(GL_ARRAY_BUFFER, m_data->m_size, m_data->m_memory,
  335. GL_STATIC_DRAW);
  336. glBindBuffer(GL_ARRAY_BUFFER, 0);
  337. }
  338. } /* namespace lol */