Buffer.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /**
  2. * Copyright (c) 2006-2017 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "Buffer.h"
  21. #include "Graphics.h"
  22. #include "common/Exception.h"
  23. namespace love
  24. {
  25. namespace graphics
  26. {
  27. Buffer::Buffer(size_t size, BufferType type, vertex::Usage usage, uint32 mapflags)
  28. : size(size)
  29. , type(type)
  30. , usage(usage)
  31. , map_flags(mapflags)
  32. , is_mapped(false)
  33. {
  34. }
  35. Buffer::~Buffer()
  36. {
  37. }
  38. // QuadIndices
  39. static const int MAX_VERTICES_PER_DRAW = LOVE_UINT16_MAX;
  40. static const int MAX_QUADS_PER_DRAW = MAX_VERTICES_PER_DRAW / 4;
  41. size_t QuadIndices::objectCount = 0;
  42. Buffer *QuadIndices::indexBuffer = nullptr;
  43. QuadIndices::QuadIndices(Graphics *gfx)
  44. {
  45. if (indexBuffer == nullptr)
  46. {
  47. size_t buffersize = sizeof(uint16) * MAX_QUADS_PER_DRAW * 6;
  48. indexBuffer = gfx->newBuffer(buffersize, nullptr, BUFFER_INDEX, vertex::USAGE_STATIC, 0);
  49. Buffer::Mapper map(*indexBuffer);
  50. vertex::fillIndices(vertex::TriangleIndexMode::QUADS, 0, MAX_VERTICES_PER_DRAW, (uint16 *) map.get());
  51. }
  52. objectCount++;
  53. }
  54. QuadIndices::QuadIndices(const QuadIndices &)
  55. {
  56. objectCount++;
  57. }
  58. QuadIndices &QuadIndices::operator = (const QuadIndices &)
  59. {
  60. return *this;
  61. }
  62. QuadIndices::~QuadIndices()
  63. {
  64. --objectCount;
  65. // Delete the buffer if we were the last living QuadIndices object.
  66. if (objectCount <= 0)
  67. {
  68. delete indexBuffer;
  69. indexBuffer = nullptr;
  70. }
  71. }
  72. static inline void advanceVertexOffsets(const vertex::Attributes &attributes, vertex::Buffers &buffers, int vertexcount)
  73. {
  74. // TODO: Figure out a better way to avoid touching the same buffer multiple
  75. // times, if multiple attributes share the buffer.
  76. uint32 touchedbuffers = 0;
  77. for (unsigned int i = 0; i < vertex::Attributes::MAX; i++)
  78. {
  79. if (!attributes.isEnabled(i))
  80. continue;
  81. auto &attrib = attributes.attribs[i];
  82. uint32 bufferbit = 1u << attrib.bufferindex;
  83. if ((touchedbuffers & bufferbit) == 0)
  84. {
  85. touchedbuffers |= bufferbit;
  86. buffers.info[attrib.bufferindex].offset += attrib.stride * vertexcount;
  87. }
  88. }
  89. }
  90. void QuadIndices::draw(Graphics *gfx, int quadstart, int quadcount, const vertex::Attributes &attributes, vertex::Buffers buffers, Texture *texture)
  91. {
  92. Graphics::DrawIndexedCommand cmd(&attributes, &buffers, indexBuffer);
  93. cmd.primitiveType = PRIMITIVE_TRIANGLES;
  94. cmd.indexBufferOffset = 0;
  95. cmd.indexType = INDEX_UINT16;
  96. cmd.texture = texture;
  97. // TODO: We can use glDrawElementsBaseVertex when supported, instead of
  98. // advancing the vertex offset.
  99. if (quadstart > 0)
  100. advanceVertexOffsets(attributes, buffers, quadstart * 4);
  101. for (int quadindex = 0; quadindex < quadcount; quadindex += MAX_QUADS_PER_DRAW)
  102. {
  103. int quaddrawcount = std::min(MAX_QUADS_PER_DRAW, quadcount - quadindex);
  104. if (quadindex > 0)
  105. advanceVertexOffsets(attributes, buffers, quaddrawcount * 4);
  106. cmd.indexCount = quaddrawcount * 6;
  107. gfx->draw(cmd);
  108. }
  109. }
  110. Buffer *QuadIndices::getBuffer() const
  111. {
  112. return indexBuffer;
  113. }
  114. } // graphics
  115. } // love