OGLIndexBuffer.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Context.h"
  25. #include "Graphics.h"
  26. #include "GraphicsImpl.h"
  27. #include "IndexBuffer.h"
  28. #include "Log.h"
  29. #include <GLee.h>
  30. #include "DebugNew.h"
  31. OBJECTTYPESTATIC(IndexBuffer);
  32. IndexBuffer::IndexBuffer(Context* context) :
  33. Object(context),
  34. GPUObject(GetSubsystem<Graphics>()),
  35. indexCount_(0),
  36. indexSize_(0),
  37. dynamic_(false),
  38. locked_(false)
  39. {
  40. }
  41. IndexBuffer::~IndexBuffer()
  42. {
  43. Release();
  44. }
  45. void IndexBuffer::Release()
  46. {
  47. if (object_)
  48. {
  49. if (!graphics_)
  50. return;
  51. if (graphics_->GetIndexBuffer() == this)
  52. graphics_->SetIndexBuffer(0);
  53. glDeleteBuffers(1, &object_);
  54. }
  55. fallbackData_.Reset();
  56. }
  57. bool IndexBuffer::SetSize(unsigned indexCount, bool largeIndices, bool dynamic)
  58. {
  59. return SetSize(indexCount, largeIndices ? sizeof(unsigned) : sizeof(unsigned short), dynamic);
  60. }
  61. bool IndexBuffer::SetSize(unsigned indexCount, unsigned indexSize, bool dynamic)
  62. {
  63. if ((indexSize != sizeof(unsigned)) && (indexSize != sizeof(unsigned short)))
  64. {
  65. LOGERROR("Index size not 2 or 4 bytes");
  66. return false;
  67. }
  68. dynamic_ = dynamic;
  69. indexCount_ = indexCount;
  70. indexSize_ = indexSize;
  71. return Create();
  72. }
  73. bool IndexBuffer::SetData(const void* data)
  74. {
  75. if (!data)
  76. {
  77. LOGERROR("Null pointer for index buffer data");
  78. return false;
  79. }
  80. if (locked_)
  81. Unlock();
  82. if (object_)
  83. {
  84. graphics_->SetIndexBuffer(this);
  85. glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount_ * indexSize_, data);
  86. return true;
  87. }
  88. else if (fallbackData_)
  89. {
  90. memcpy(fallbackData_.GetPtr(), data, indexCount_ * indexSize_);
  91. return true;
  92. }
  93. return false;
  94. }
  95. bool IndexBuffer::SetDataRange(const void* data, unsigned start, unsigned count)
  96. {
  97. if (!data)
  98. {
  99. LOGERROR("Null pointer for index buffer data");
  100. return false;
  101. }
  102. if (start + count > indexCount_)
  103. {
  104. LOGERROR("Illegal range for setting new index buffer data");
  105. return false;
  106. }
  107. if (locked_)
  108. Unlock();
  109. if (object_)
  110. {
  111. graphics_->SetIndexBuffer(this);
  112. glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, start * indexSize_, indexCount_ * indexSize_, data);
  113. return true;
  114. }
  115. else if (fallbackData_)
  116. {
  117. memcpy(fallbackData_.GetPtr() + start * indexSize_, data, indexCount_ * indexSize_);
  118. return true;
  119. }
  120. return false;
  121. }
  122. void* IndexBuffer::Lock(unsigned start, unsigned count, LockMode mode)
  123. {
  124. if ((!object_) && (!fallbackData_))
  125. return 0;
  126. if (locked_)
  127. {
  128. LOGERROR("Index buffer already locked");
  129. return 0;
  130. }
  131. if ((!count) || (start + count > indexCount_))
  132. {
  133. LOGERROR("Illegal range for locking index buffer");
  134. return 0;
  135. }
  136. void* hwData = 0;
  137. GLenum glLockMode = GL_WRITE_ONLY;
  138. if (mode == LOCK_READONLY)
  139. glLockMode = GL_READ_ONLY;
  140. else if (mode == LOCK_NORMAL)
  141. glLockMode = GL_READ_WRITE;
  142. if (object_)
  143. {
  144. graphics_->SetIndexBuffer(this);
  145. hwData = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, glLockMode);
  146. if (!hwData)
  147. return 0;
  148. hwData = (unsigned char*)hwData + start * indexSize_;
  149. }
  150. else
  151. hwData = fallbackData_.GetPtr() + start * indexSize_;
  152. locked_ = true;
  153. return hwData;
  154. }
  155. void IndexBuffer::Unlock()
  156. {
  157. if (locked_)
  158. {
  159. if (object_)
  160. {
  161. graphics_->SetIndexBuffer(this);
  162. glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
  163. }
  164. locked_ = false;
  165. }
  166. }
  167. bool IndexBuffer::GetUsedVertexRange(unsigned start, unsigned count, unsigned& minVertex, unsigned& vertexCount)
  168. {
  169. void* data = Lock(start, count, LOCK_READONLY);
  170. if (!data)
  171. return false;
  172. minVertex = M_MAX_UNSIGNED;
  173. unsigned maxVertex = 0;
  174. if (indexSize_ == sizeof(unsigned))
  175. {
  176. unsigned* indices = (unsigned*)data;
  177. for (unsigned i = 0; i < count; ++i)
  178. {
  179. if (indices[i] < minVertex)
  180. minVertex = indices[i];
  181. if (indices[i] > maxVertex)
  182. maxVertex = indices[i];
  183. }
  184. }
  185. else
  186. {
  187. unsigned short* indices = (unsigned short*)data;
  188. for (unsigned i = 0; i < count; ++i)
  189. {
  190. if (indices[i] < minVertex)
  191. minVertex = indices[i];
  192. if (indices[i] > maxVertex)
  193. maxVertex = indices[i];
  194. }
  195. }
  196. vertexCount = maxVertex - minVertex + 1;
  197. Unlock();
  198. return true;
  199. }
  200. bool IndexBuffer::Create()
  201. {
  202. Release();
  203. if (!indexCount_)
  204. return true;
  205. if (graphics_)
  206. {
  207. glGenBuffers(1, &object_);
  208. graphics_->SetIndexBuffer(this);
  209. glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  210. }
  211. else
  212. fallbackData_ = new unsigned char[indexCount_ * indexSize_];
  213. return true;
  214. }